ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript コード最適化に関する 10 のヒントの要約と共有

JavaScript コード最適化に関する 10 のヒントの要約と共有

WBOY
WBOY転載
2022-08-01 15:00:381585ブラウズ

この記事は、javascript に関する関連知識を提供します。主に 10 の JavaScript コード最適化のヒントの概要と共有を紹介します。この記事では、特定の参考価値のあるテーマを中心に詳細な紹介が提供されます。みんなが助けてくれることを願っています。

JavaScript コード最適化に関する 10 のヒントの要約と共有

[関連する推奨事項: JavaScript ビデオ チュートリアルWeb フロントエンド]

前に書く

JavaScript コードの最適化を実現するには、まず JavaScript コードの実行時間を正確にテストする必要があります。実際に行う必要があるのは、数学的な統計と分析のために大量の実行サンプルを収集することです。ここでは、benchmark.js を使用してコードの実行を検出します。

最初にプロジェクトに依存関係をインストールする必要があります。コードは次のとおりです:

yarn add benchmark --save
# 或者
npm i benchmark --save

次に、次のようなテスト コードを作成します:

const Benchmark = require('benchmark')
const suite = new Benchmark.Suite()
// 添加测试
suite
  /**
   * add() 方法接受两个参数,其中第一个表示测试的名称,第二个表示测试的内容,他是一个函数*   
/
  .add('join1000', () => {
    new Array(1000).join(' ')
  })
  .add('join10000', () => {
    new Array(10000).join(' ')
  })
  // 添加时间监听
  .on('cycle', event => {
    // 打印执行时间
    console.log(String(event.target))
  })
  // 完成后执行触发的事件
  .on('complete', () => {
    console.log('最快的是:' + suite.filter('fastest').map('name'))
  })
  // 执行测试
  .run({ async: true })

复制代码

コードの実行結果は次のとおりです:

// join1000 x 146,854 ops/sec ±1.86% (88 回の実行がサンプリングされました)
/ / join10000 x 16,083 ops /sec ±1.06% (92 回の実行がサンプリング)
// 最速は次のとおりです: join1000

結果の ops/sec は 1 回あたりの実行を表します。秒 回数はもちろん大きいほど良いのですが、次に 1 秒あたりの実行時間の上限と下限の差のパーセンテージが続き、最後に括弧内の内容がサンプリング回数の合計を示します。 join1000 のパフォーマンスが優れていることがわかります (ナンセンスなことを言っているように感じます)。

グローバル変数は注意して使用してください

ここで説明されているグローバル変数は注意して使用する必要があります。なぜ注意して使用する必要があるのですか?主なポイントは次のとおりです。

  • グローバル変数は、グローバル実行コンテキストで定義され、すべてのスコープ チェーンの最上位にあります。検索するたびに上から順に探していくことになるので時間がかかります。
  • グローバル実行コンテキストは常にコンテキストの実行スタックに存在し、プログラムが終了するまで破棄されません。これはメモリ領域の無駄です。
  • 同じ名前の変数がローカル スコープに出現すると、グローバル変数がカバーされるか汚染されます。
# グローバル変数とレイアウト変数の実行効率の違いを確認するコードを書いてみましょう。コードは次のとおりです:

...
suite
  .add('全局变量', () => {
    // 该函数内模拟全局作用域
    let i,
      str = ''
    for (i = 0; i < 1000; i++) {
      str += i
    }
  })
  .add(&#39;局部变量&#39;, () => {
    for (let i = 0, str = &#39;&#39;; i < 1000; i++) {
      str += i
    }
  })
...

コードの実行結果は次のとおりです。

グローバル変数 x 158,697 ops/秒 ±1.05% (87 回の実行がサンプリングされました)
ローカル変数 x 160,697 ops/秒 ±1.03% ( 90 回の実行がサンプリングされました)

最も速いのはローカル変数です。

差は大きくありませんが、グローバル変数のパフォーマンスがローカル変数のパフォーマンスより悪いことがわかります。

プロトタイプを介してメソッドを追加する

インスタンス オブジェクトに必要なメソッドをコンストラクターに追加するときは、コンストラクター内に追加するのではなく、プロトタイプを使用して追加するようにしてください。次のテスト コードが表示されます。

...
suite
  .add(&#39;构造函数内部添加&#39;, () => {
    function Person() {
      this.sayMe = function () {
        return &#39;一碗周&#39;
      }
    }
    let p = new Person()
  })
  .add(&#39;原型方式内部添加&#39;, () => {
    function Person() {}
    Person.prototype.sayMe = function () {
      return &#39;一碗周&#39;
    }
    let p = new Person()
  })
...

コードの実行結果は次のとおりです:

コンストラクター内に x 573,786 ops/秒 ±1.97% (89 回の実行がサンプリング) を追加します。プロトタイプ メソッド内でパッケージを追加すると、関数内の変数がメモリに格納され、大量のメモリが消費されるため、クロージャを悪用することはできません。そうしないと、Web ページでパフォーマンスの問題が発生し、深刻なメモリ リークにつながる可能性があります。 。解決策は、関数を終了する前に未使用のローカル変数をすべて削除することです (つまり、ローカル変数を
null

に再割り当てします)。

プロパティ アクセス メソッドの使用を避ける

JavaScript のオブジェクトでは、一部のプロパティ アクセス メソッドの使用を避けてください。これは、JavaScript のすべてのプロパティが外部から参照できるためです。

サンプル コードは次のとおりです:

...
suite
  .add(&#39;使用属性访问方法&#39;, () => {
    function Person() {
      this.name = &#39;一碗周&#39;
      this.getName = function () {
        return &#39;一碗周&#39;
      }
    }
    let p = new Person()
    let n = p.getName()
  })
  .add(&#39;不使用属性访问方法&#39;, () => {
    function Person() {
      this.name = &#39;一碗周&#39;
    }
    let p = new Person()
    let n = p.name
  })
...

コードの実行結果は次のとおりです:

Use属性アクセス メソッド x 406,682 ops/秒 ±2.33% (82 実行サンプル) 属性アクセス メソッドを使用しません x 554,169 ops/秒 ±2.03% (85 実行サンプル) 最速: 属性アクセス メソッドを使用しません

for ループの最適化

for ループを使用すると、
arr.length

などの必要なデータをキャッシュできますが、これはキャッシュする必要はありません。コードを最適化するために、判定されるたびに取得されます。

サンプル コードは次のとおりです。

...
suite
  .add(&#39;正序&#39;, () => {
    let arr = new Array(100)
    let str = &#39;&#39;
    for (let i = 0; i < arr.length; i++) {
      str += i
    }
  })
  .add(&#39;缓存&#39;, () => {
    let arr = new Array(100)
    let str = &#39;&#39;
    for (let i = arr.length; i; i--) {
      str += i
    }
  })
  .add(&#39;缓存的另一种写法&#39;, () => {
    let arr = new Array(100)
    let str = &#39;&#39;
    for (let i = 0, l = arr.length; i < l; i++) {
      str += i
    }
  })
...

コードの実行結果は次のとおりです。

Forwardシーケンス x 1,322,889 ops/秒 ±1.36% (86 実行がサンプリング) キャッシュ x 1,356,696 ops/秒 ±0.70% (92 実行がサンプリング) キャッシュを書き込む別の方法 x 1,383,091 ops/秒 ±0.70% (93 実行)サンプル)

最も速いのは、キャッシュを記述する別の方法です。

最適なループ方法を選択します。

現在一般的に使用されているループには、

forEach
,# が含まれます。 ##for
ループと
for...in

ループ、どちらが最高のパフォーマンスを持っていますか? テスト コードは次のとおりです:
...
suite
  .add(&#39;forEach&#39;, () => {
    let arr = new Array(100)
    let str = &#39;&#39;
    arr.forEach(i => {
      str += i
    })
  })
  .add(&#39;for...in&#39;, () => {
    let arr = new Array(100)
    let str = &#39;&#39;
    for (i in arr) {
      str += i
    }
  })
  .add(&#39;for&#39;, () => {
    let arr = new Array(100)
    let str = &#39;&#39;
    for (let i = 0, l = arr.length; i < l; i++) {
      str += i
    }
  })
...

コードの実行結果は次のとおりです。以下:

<blockquote><p>forEach x 4,248,577 ops/sec ±0.89% (86 runs sampled)<br>for...in x 4,583,375 ops/sec ±1.15% (91 runs sampled)<br>for x 1,343,871 ops/sec ±1.91% (88 runs sampled)<br>最快的是:for...in</p></blockquote> <p>由运行结果可以看出我们可以尽量使用<code>for...in或者forEach循环,减少使用for循环。

减少判断层级

减少判断层级就是减少一些if语句的嵌套,如果是一些必要的条件我们可以通过单层if结合return直接跳出函数的执行,关于优化前与优化后的代码执行比对如下所示:

...
/*** 
 接收两类文件,zip 和 rar* 
 压缩包的大小限制为 10 兆* 
/

suite
  .add(&#39;嵌套写法&#39;, () => {
    function uploadFile(suffix, size) {
      // 允许上传的后缀名
      const suffixList = [&#39;.zip&#39;, &#39;.rar&#39;]
      const M = 1024*  1024

      if (suffixList.includes(suffix)) {
        if (size <= 10*  M) {
          return &#39;下载成功&#39;
        }
      }
    }
    uploadFile(&#39;.zip&#39;, 1*  1024*  1024)
  })
  .add(&#39;减少判断写法&#39;, () => {
    function uploadFile(suffix, size) {
      // 允许上传的后缀名
      const suffixList = [&#39;.zip&#39;, &#39;.rar&#39;]
      const M = 1024*  1024
      if (!suffixList.includes(suffix)) return
      if (size > 10*  M) return
      return &#39;下载成功&#39;
    }
    uploadFile(&#39;.zip&#39;, 1*  1024*  1024)
  })
...

代码运行结果如下:

嵌套写法 x 888,445,014 ops/sec ±2.48% (88 runs sampled)
减少判断写法 x 905,763,884 ops/sec ±1.35% (92 runs sampled)
最快的是:减少判断写法,嵌套写法

虽然说差距并不是很大,但是不适用嵌套的代码比普通代码更优一些。

减少作用域链查找层级

减少代码中作用域链的查找也是代码优化的一种方法,如下代码展示了两者的区别:

...
suite
  .add(&#39;before&#39;, () => {
    var name = &#39;一碗粥&#39;
    function sayMe() {
      name = &#39;一碗周&#39;
      function print() {
        var age = 18
        return name + age
      }
      print()
    }
    sayMe()
  })
  .add(&#39;after&#39;, () => {
    var name = &#39;一碗粥&#39;
    function sayMe() {
      var name = &#39;一碗周&#39; // 形成局部作用域
      function print() {
        var age = 18
        return name + age
      }
      print()
    }
    sayMe()
  })
...

代码运行结果如下:

before x 15,509,793 ops/sec ±7.78% (76 runs sampled)
after x 17,930,066 ops/sec ±2.89% (83 runs sampled)
最快的是:after

上面代码只是为了展示区别,并没有实际意义。

减少数据读取次数

如果对象中的某个数据在一个代码块中使用两遍以上,这样的话将其进行缓存从而减少数据的读取次数来达到更优的一个性能,

测试代码如下:

...
var userList = {
  one: {
    name: &#39;一碗周&#39;,
    age: 18,
  },
  two: {
    name: &#39;一碗粥&#39;,
    age: 18,
  },
}
suite
  .add(&#39;before&#39;, () => {
    function returnOneInfo() {
      userList.one.info = userList.one.name + userList.one.age
    }
    returnOneInfo()
  })
  .add(&#39;after&#39;, () => {
    function returnOneInfo() {
      let one = userList.one
      one.info = one.name + one.age
    }
    returnOneInfo()
  })
...

代码运行结果如下:

before x 222,553,199 ops/sec ±16.63% (26 runs sampled)
after x 177,894,903 ops/sec ±1.85% (88 runs sampled)
最快的是:before

字面量与构造式

凡是可以使用字面量方式声明的内容,绝对是不可以使用构造函数的方式声明的,两者在性能方面相差甚远,代码如下:

...
suite
  .add(&#39;before&#39;, () => {
    var str = new String(&#39;string&#39;)
  })
  .add(&#39;after&#39;, () => {
    var str = &#39;string&#39;
  })
...

代码运行结果如下:

before x 38,601,223 ops/sec ±1.16% (89 runs sampled)
after x 897,491,903 ops/sec ±0.92% (92 runs sampled)
最快的是:after

【相关推荐:javascript视频教程web前端

以上がJavaScript コード最適化に関する 10 のヒントの要約と共有の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjb51.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。