ホームページ ウェブフロントエンド jsチュートリアル コードの実行が遅いですか?プログラムの高速実行を維持するには、JavaScript と Node.js でよくある 19 の間違いを回避してください

コードの実行が遅いですか?プログラムの高速実行を維持するには、JavaScript と Node.js でよくある 19 の間違いを回避してください

Sep 22, 2023 am 10:50 AM
javascript node.js

Web サイトが遅い、または遅れているのはアマチュアの兆候ですが、スムーズで最適化されたエクスペリエンスはユーザーを喜ばせ、プロとは一線を画します。

しかし、本当に高パフォーマンスの Web アプリケーションを作成するには、落とし穴がたくさんあります。バグはたくさんあり、気付かないうちに JavaScript の速度を低下させる可能性があります。小さな見落としがあるとコードが肥大化し、静かに少しずつ速度が低下する可能性があります。

これはどうなりましたか?

意図せずに JavaScript の速度を低下させる一般的な方法が多数あることが判明しました。時間が経つと、これにより Web サイトのパフォーマンスが妨げられる可能性があります。

これらの間違いは避けることができます。

今日は、JavaScript および Node.js アプリケーションの速度を静かに低下させる可能性がある 19 のパフォーマンスの落とし穴に焦点を当てます。コードを最適化するための具体的な例と実用的な解決策を使用して、これらの問題の原因を探ります。

ユーザーを満足させるスムーズな Web エクスペリエンスを作成するには、これらの危険を特定して排除することが重要です。それでは、詳しく見ていきましょう!

1. 間違った変数宣言とスコープ

JavaScript を初めて学習する場合、すべての変数をグローバルに宣言するのは簡単です。ただし、これは将来的に問題を引き起こす可能性があります。例を見てみましょう:

// globals.js
var color = 'blue';
function printColor() {
  console.log(color); 
}
printColor(); // Prints 'blue'
ログイン後にコピー

これは正常に動作しますが、別のスクリプトをロードした場合を想像してください:

// script2.js
var color = 'red';
printColor(); // Prints 'red'!
ログイン後にコピー

color はグローバルなので、script2.js がそれをオーバーライドします。この問題を解決するには、可能な限り関数内で変数を宣言します。

function printColor() {
  var color = 'blue'; // local variable
  
  console.log(color);
}
printColor(); // Prints 'blue'
ログイン後にコピー

他のスクリプトからの変更は printColor に影響しません。

不必要な場合にグローバル スコープで変数を宣言するのはアンチパターンです。グローバル変数を構成定数に限定してみてください。他の変数については、可能な限り最小のスコープでローカルに宣言します。

2. 非効率的な DOM 操作

DOM 要素を更新するときは、一度に 1 つのノードを操作するのではなく、バッチ変更を行ってください。次の例を考えてみましょう:

const ul = document.getElementById('list');
for (let i = 0; i < 10; i++) {
  const li = document.createElement(&#39;li&#39;);
  li.textContent = i;
  
  ul.appendChild(li);
}
ログイン後にコピー

これにより、リスト項目が 1 つずつ追加されます。最初に文字列を構築してから、.innerHTML を設定することをお勧めします。

const ul = document.getElementById(&#39;list&#39;);
let html = &#39;&#39;;
for (let i = 0; i < 10; i++) {
  html += `<li>${i}</li>`; 
}
ul.innerHTML = html;
ログイン後にコピー

文字列を構築すると、リフローが最小限に抑えられます。 DOM を 10 回ではなく 1 回更新します。

複数の更新の場合は、変更をビルドして最後に適用します。さらに良いのは、DocumentFragment を使用してバッチ追加することです。

3. 過剰な DOM 操作

DOM を頻繁に更新すると、パフォーマンスが低下します。ページにメッセージを挿入するチャット アプリケーションを考えてみましょう。

否定的な例:

// New message received
const msg = `<div>${messageText}</div>`;
chatLog.insertAdjacentHTML(&#39;beforeend&#39;, msg);
ログイン後にコピー

これはすべてのメッセージに単純に挿入されます。更新を制限することをお勧めします:

正しい例:

let chatLogHTML = &#39;&#39;;
const throttleTime = 100; // ms
// New message received  
chatLogHTML += `<div>${messageText}</div>`;
// Throttle DOM updates
setTimeout(() => {
  chatLog.innerHTML = chatLogHTML;
  chatLogHTML = &#39;&#39;; 
}, throttleTime);
ログイン後にコピー

現在、更新は最大 100 ミリ秒ごとに行われるため、DOM 操作が低く抑えられます。

非常に動的な UI の場合は、React のような仮想 DOM ライブラリを検討してください。これらにより、仮想表現を使用した DOM 操作が最小限に抑えられます。

4. アクティビティ委任の欠如

イベント リスナーを多くの要素にアタッチすると、不要なオーバーヘッドが発生します。各行に削除ボタンがあるテーブルを考えてみましょう:

否定的な例:

const rows = document.querySelectorAll(&#39;table tr&#39;);
rows.forEach(row => {
  const deleteBtn = row.querySelector(&#39;.delete&#39;);  
  deleteBtn.addEventListener(&#39;click&#39;, handleDelete);
});
ログイン後にコピー

これにより、各削除ボタンにリスナーが追加されます。イベント委任をより適切に使用する必要があります:

正しい例:

const table = document.querySelector(&#39;table&#39;);
table.addEventListener(&#39;click&#39;, e => {
  if (e.target.classList.contains(&#39;delete&#39;)) {
    handleDelete(e);
  }
});
ログイン後にコピー

現在、.net にはリスナーが 1 つだけあり、メモリ オーバーヘッドが少なくなります。

イベント委任ではイベント バブリングを使用します。リスナーは複数の子孫からのイベントを処理できます。該当する場合は常に委任を使用します。

5. 非効率的な文字列の連結

ループ内で文字列を連結すると、パフォーマンスに影響します。次のコードを考えてみましょう:

let html = &#39;&#39;;
for (let i = 0; i < 10; i++) {
  html += &#39;<div>&#39; + i + &#39;</div>&#39;;
}
ログイン後にコピー

新しい文字列を作成するには、メモリを割り当てる必要があります。配列を使用することをお勧めします。

const parts = [];
for (let i = 0; i < 10; i++) {
  parts.push(&#39;<div>&#39;, i, &#39;</div>&#39;);
}
const html = parts.join(&#39;&#39;);
ログイン後にコピー

配列を構築すると、中間文字列の数が最小限に抑えられます。 .join() は最後に結合します。

複数の文字列を追加するには、配列連結を使用してください。また、値を埋め込むテンプレート リテラルも考慮してください。

6. 最適化されていないループ

JavaScript のループは、パフォーマンスの問題を引き起こすことがよくあります。よくある間違いは、配列の長さに繰り返しアクセスすることです。

反例:

const items = [/*...*/];
for (let i = 0; i < items.length; i++) {
  // ...
}
ログイン後にコピー

.length の冗長チェックにより、最適化が妨げられる可能性があります。

正しい例:

const items = [/*...*/];  
const len = items.length;
for (let i = 0; i < len; i++) {
  // ...
}
ログイン後にコピー

キャッシュの長さにより速度が向上します。その他の最適化には、ループ外の不変条件の除去、終了条件の簡素化、反復内での負荷の高い操作の回避などが含まれます。

7. 不要な同期操作

JavaScript 的异步功能是一个关键优势。但要小心阻塞 I/O!例如:

反面例子:

const data = fs.readFileSync(&#39;file.json&#39;); // blocks!
ログイン後にコピー

这会在从磁盘读取时停止执行。相反,如果使用回调或承诺:

正确示例:

fs.readFile(&#39;file.json&#39;, (err, data) => {
  // ...
});
ログイン後にコピー

现在,事件循环在读取文件时继续。对于复杂的流程,async/await简化异步逻辑。避免同步操作以防止阻塞。

8. 阻止事件循环

JavaScript 使用单线程事件循环。阻止它会停止执行。一些常见的拦截器:

繁重的计算任务

同步输入/输出

未优化的算法

例如:

function countPrimes(max) {
  // Unoptimized loop
  for (let i = 0; i <= max; i++) {
    // ...check if prime...
  }
}
countPrimes(1000000); // Long running!
ログイン後にコピー

这会同步执行,并阻止其他事件。避免:

推迟不必要的工作

批量数据处理

使用工作线程

寻找优化机会

保持事件循环顺利运行。定期分析以捕获阻塞代码。

9. 错误处理效率低下

在 JavaScript 中正确处理错误至关重要。但要小心性能陷阱!

反面例子:

try {
  // ...
} catch (err) {
  console.error(err); // just logging
}
ログイン後にコピー

这会捕获错误但不采取纠正措施。未处理的错误通常会导致内存泄漏或数据损坏。

正确示例:

try {
  // ...
} catch (err) {
  console.error(err);
  
  // Emit error event 
  emitError(err); 
  
  // Nullify variables
  obj = null;
  
  // Inform user
  showErrorNotice();
}
ログイン後にコピー

记录还不够!清理工件、通知用户并考虑恢复选项。使用 Sentry 等工具来监控生产中的错误。明确处理所有错误。

10. 内存泄漏

当内存被分配但从未释放时,就会发生内存泄漏。随着时间的推移,泄漏会累积并降低性能。

JavaScript 中的常见来源包括:

未清理的事件监听器

对已删除 DOM 节点的过时引用

不再需要的缓存数据

闭包中的累积状态

例如:

function processData() {
  const data = [];
  // Use closure to accumulate data
  return function() {
    data.push(getData()); 
  }
}
const processor = processData();
// Long running...keeps holding reference to growing data array!
ログイン後にコピー

数组不断变大,但从未被清除。修理:

使用弱引用

清理事件监听器

删除不再需要的引用

限制关闭状态大小

监视内存使用情况并观察增长趋势。在泄漏堆积之前主动消除泄漏。

11. 过度使用依赖项

虽然 npm 提供了无穷无尽的选择,但请抵制过度导入的冲动!每个依赖项都会增加包大小和攻击面。

反面例子:

import _ from &#39;lodash&#39;;
import moment from &#39;moment&#39;; 
import validator from &#39;validator&#39;;
// etc...
ログイン後にコピー

为次要实用程序导入整个库。最好根据需要挑选助手:

正确示例:

import cloneDeep from &#39;lodash/cloneDeep&#39;;
import { format } from &#39;date-fns&#39;;
import { isEmail } from &#39;validator&#39;;
ログイン後にコピー

只导入您需要的内容。定期检查依赖关系以删除未使用的依赖关系。保持捆绑精简并最大限度地减少依赖性。

12. 缓存不足

缓存允许通过重用先前的结果来跳过昂贵的计算。但它经常被忽视。

反面例子:

function generateReport() {
  // Perform expensive processing
  // to generate report data... 
}
generateReport(); // Computes
generateReport(); // Computes again!
ログイン後にコピー

由于输入没有更改,因此可以缓存报告:

正确示例:

let cachedReport;
function generateReport() {
  if (cachedReport) {
    return cachedReport;
  }
  cachedReport = // expensive processing...
  return cachedReport; 
}
ログイン後にコピー

现在,重复调用速度很快。

13. 未优化的数据库查询

与数据库交互时,低效的查询可能会降低性能。需要避免的一些问题:

反面例子:

// No indexing
db.find({name: &#39;John&#39;, age: 35}); 
// Unecessary fields
db.find({first: &#39;John&#39;, last:&#39;Doe&#39;, email:&#39;john@doe.com&#39;}, {first: 1, last: 1});
// Too many separate queries
for (let id of ids) {
  const user = db.find({id});
}
ログイン後にコピー

这无法利用索引、检索未使用的字段并执行过多的查询。

正确示例:

// Use index on &#39;name&#39; 
db.find({name: &#39;John&#39;}).hint({name: 1});
// Only get &#39;email&#39; field
db.find({first: &#39;John&#39;}, {email: 1}); 
// Get users in one query
const users = db.find({
  id: {$in: ids} 
});
ログイン後にコピー

分析并解释计划。战略性地创建索引。避免多次零散的查询。优化数据存储交互。

14. Promise 中错误处理不当

Promise 简化了异步代码。但未经处理的拒绝就是无声的失败!

反面例子:

function getUser() {
  return fetch(&#39;/user&#39;)
    .then(r => r.json()); 
}
getUser();
ログイン後にコピー

如果fetch拒绝,异常就不会被注意到。

正确示例:

function getUser() {
  return fetch(&#39;/user&#39;)
    .then(r => r.json())
    .catch(err => console.error(err));
} 
getUser();
ログイン後にコピー

链接.catch()可以正确处理错误。

15. 同步网络操作

网络请求应该是异步的。但有时会使用同步变体:

反面例子:

const data = http.getSync(&#39;http://example.com/data&#39;); // blocks!
ログイン後にコピー

这会在请求期间停止事件循环。相反,使用回调:

正确示例:

http.get(&#39;http://example.com/data&#39;, res => {
  // ...
});
ログイン後にコピー

或者:

fetch(&#39;http://example.com/data&#39;)
  .then(res => res.json())
  .then(data => {
    // ...
  });
ログイン後にコピー

异步网络请求允许在等待响应时进行其他处理。避免同步网络调用。

16. 低效的文件 I/O 操作

读/写文件同步阻塞。例如:

反面例子:

const contents = fs.readFileSync(&#39;file.txt&#39;); // blocks!
ログイン後にコピー

这会在磁盘 I/O 期间停止执行。

正确示例:

fs.readFile(&#39;file.txt&#39;, (err, contents) => {
  // ...
});
// or promises
fs.promises.readFile(&#39;file.txt&#39;)
   .then(contents => {
     // ...  
   });
ログイン後にコピー

这允许事件循环在文件读取期间继续。

对于多个文件,使用流:

function processFiles(files) {
  for (let file of files) {
    fs.createReadStream(file)
      .pipe(/*...*/);
  }
}
ログイン後にコピー

避免同步文件操作。使用回调、promise 和流。

17. 忽略性能分析和优化

在出现明显问题之前,很容易忽视性能。但优化应该持续进行!首先使用分析工具进行测量:

浏览器开发工具时间线

Node.js 分析器

第三方分析器

即使性能看起来不错,这也揭示了优化机会:

// profile.js
function processOrders(orders) {
  orders.forEach(o => {
    // ...
  });
}
processOrders(allOrders);
ログイン後にコピー

分析器显示processOrders需要 200 毫秒。

分析指导优化。制定绩效预算,如果超出则失败。经常测量并明智地优化。

18. 不利用缓存机制

缓存通过避免重复工作来提高速度。但它经常被遗忘。

反面例子:

// Compute expensive report
function generateReport() {
  // ...heavy processing...
}
generateReport(); // Computes
generateReport(); // Computes again!
ログイン後にコピー

相同的输入总是产生相同的输出。我们应该缓存:

正确示例:

// Cache report contents
const cache = {};
function generateReport() {
  if (cache.report) {
    return cache.report;
  }
  const report = // ...compute...
  cache.report = report;
  return report;
}
ログイン後にコピー

现在,重复调用速度很快。

19. 不必要的代码重复

重复的代码会损害可维护性和可优化性。

function userStats(user) {
  const name = user.name;
  const email = user.email;
  
  // ...logic...
}
function orderStats(order) {
  const name = order.customerName;
  const email = order.customerEmail;
  // ...logic... 
}
ログイン後にコピー

提取是重复的。我们重来:

function getCustomerInfo(data) {
  return {
    name: data.name, 
    email: data.email
  };
}
function userStats(user) {
  const { name, email } = getCustomerInfo(user);
  
  // ...logic...
}
function orderStats(order) {
  const { name, email } = getCustomerInfo(order);
  // ...logic...
}
ログイン後にコピー

现在,它只定义一次。

结论

优化 JavaScript 应用程序性能是一个迭代过程。通过学习有效的实践并勤于分析,可以显着提高速度。

需要关注的关键领域包括最大限度地减少 DOM 更改、利用异步技术、消除阻塞操作、减少依赖性、利用缓存以及删除不需要的重复。

以上がコードの実行が遅いですか?プログラムの高速実行を維持するには、JavaScript と Node.js でよくある 19 の間違いを回避してくださいの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 Dec 17, 2023 pm 02:54 PM

WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 はじめに: 技術の継続的な発展により、音声認識技術は人工知能の分野の重要な部分になりました。 WebSocket と JavaScript をベースとしたオンライン音声認識システムは、低遅延、リアルタイム、クロスプラットフォームという特徴があり、広く使用されるソリューションとなっています。この記事では、WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法を紹介します。

WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー Dec 17, 2023 pm 05:30 PM

WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 Dec 17, 2023 pm 12:09 PM

JavaScript と WebSocket を使用してリアルタイム オンライン注文システムを実装する方法の紹介: インターネットの普及とテクノロジーの進歩に伴い、ますます多くのレストランがオンライン注文サービスを提供し始めています。リアルタイムのオンライン注文システムを実装するには、JavaScript と WebSocket テクノロジを使用できます。 WebSocket は、TCP プロトコルをベースとした全二重通信プロトコルで、クライアントとサーバー間のリアルタイム双方向通信を実現します。リアルタイムオンラインオーダーシステムにおいて、ユーザーが料理を選択して注文するとき

WebSocketとJavaScriptを使ったオンライン予約システムの実装方法 WebSocketとJavaScriptを使ったオンライン予約システムの実装方法 Dec 17, 2023 am 09:39 AM

WebSocket と JavaScript を使用してオンライン予約システムを実装する方法 今日のデジタル時代では、ますます多くの企業やサービスがオンライン予約機能を提供する必要があります。効率的かつリアルタイムのオンライン予約システムを実装することが重要です。この記事では、WebSocket と JavaScript を使用してオンライン予約システムを実装する方法と、具体的なコード例を紹介します。 1. WebSocket とは何ですか? WebSocket は、単一の TCP 接続における全二重方式です。

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 Dec 17, 2023 pm 05:13 PM

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 はじめに: 今日、天気予報の精度は日常生活と意思決定にとって非常に重要です。テクノロジーの発展に伴い、リアルタイムで気象データを取得することで、より正確で信頼性の高い天気予報を提供できるようになりました。この記事では、JavaScript と WebSocket テクノロジを使用して効率的なリアルタイム天気予報システムを構築する方法を学びます。この記事では、具体的なコード例を通じて実装プロセスを説明します。私たちは

簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 Jan 05, 2024 pm 06:08 PM

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

JavaScriptでinsertBeforeを使用する方法 JavaScriptでinsertBeforeを使用する方法 Nov 24, 2023 am 11:56 AM

使用法: JavaScript では、insertBefore() メソッドを使用して、DOM ツリーに新しいノードを挿入します。このメソッドには、挿入される新しいノードと参照ノード (つまり、新しいノードが挿入されるノード) の 2 つのパラメータが必要です。

JavaScript と WebSocket: 効率的なリアルタイム画像処理システムの構築 JavaScript と WebSocket: 効率的なリアルタイム画像処理システムの構築 Dec 17, 2023 am 08:41 AM

JavaScript は Web 開発で広く使用されているプログラミング言語であり、WebSocket はリアルタイム通信に使用されるネットワーク プロトコルです。 2 つの強力な機能を組み合わせることで、効率的なリアルタイム画像処理システムを構築できます。この記事では、JavaScript と WebSocket を使用してこのシステムを実装する方法と、具体的なコード例を紹介します。まず、リアルタイム画像処理システムの要件と目標を明確にする必要があります。リアルタイムの画像データを収集できるカメラ デバイスがあるとします。

See all articles