xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

JavaScript code 性能优化

JavaScript 性能优化 prototype 闭包 Closure 内存泄漏 event system

定义类方法

以下是低效的,因为每次构建baz.Bar的实例时,都会为foo创建一个新函数和闭包:

baz.Bar = function() {
  // constructor body
  this.foo = function() {
    // method body
  };
}
首选方法是:

baz.Bar = function() {
  // constructor body
};

baz.Bar.prototype.foo = function() {
  // method body
};
使用这种方法,无论构建多少个baz.Bar实例,都只会为foo创建一个函数,并且不会创建闭包。

初始化实例变量

将实例变量声明/初始化放在具有值类型(而不是引用类型)初始值的实例变量的原型上(i.e. values of type number, Boolean, null, undefined, or string)

(即, 类型是 number, Boolean, null, undefined, 或 string的值)

ES 6: Symbol ???

这避免了每次调用构造函数时不必要地运行初始化代码。(对于初始值依赖于构造函数的参数的实例变量,或者构造时的某个其他状态,不能这样做。)

例如,代替

foo.Bar = function() {
  this.prop1_ = 4;
  this.prop2_ = true;
  this.prop3_ = [];
  this.prop4_ = 'blah';
};
使用:

foo.Bar = function() {
  this.prop3_ = [];
};
foo.Bar.prototype.prop1_ = 4;
foo.Bar.prototype.prop2_ = true;
foo.Bar.prototype.prop4_ = 'blah';
避免闭包的陷阱

闭包是JavaScript的一个强大而有用的特性;然而,它们有几个缺点,包括:

它们是内存泄漏的最常见的来源。
创建闭包比创建没有闭包的内部函数慢得多,并且比重用静态函数慢得多。
例如:

function setupAlertTimeout() {
  var msg = 'Message to alert';
  window.setTimeout(function() { alert(msg); }, 100);
}
慢于:

function setupAlertTimeout() {
  window.setTimeout(function() {
    var msg = 'Message to alert';
    alert(msg);
  }, 100);
}
其慢于:

function alertMsg() {
  var msg = 'Message to alert';
  alert(msg);
}

function setupAlertTimeout() {
  window.setTimeout(alertMsg, 100);
}
它们向作用域链添加级别。当浏览器解析属性时,必须检查作用域链的每个级别。在以下示例中:

var a = 'a';

function createFunctionWithClosure() {
  var b = 'b';
  return function () {
    var c = 'c';
    a;
    b;
    c;
  };
}

var f = createFunctionWithClosure();
f();
当调用f时,引用a比引用b慢,这比引用c慢。

有关何时使用闭包与IE的信息的, 请参阅IE + JScript性能建议第3部分:JavaScript代码效率低下 。

避免使用 with

避免在代码中使用 with 。它对性能有负面影响,因为它修改了作用域链,使得在其他作用域中查找变量更加昂贵。

Avoiding browser memory leaks

内存泄漏是Web应用程序的一个常见的问题,可能导致巨大的性能损失。随着浏览器的内存使用量的增长,您的Web应用程序以及用户系统的其余部分会减慢。

Web应用程序最常见的内存泄漏包括JavaScript脚本引擎和浏览器的C ++对象实现DOM之间的循环引用 ( 例如JavaScript脚本引擎和Internet Explorer的COM基础结构之间,或JavaScript引擎和Firefox XPCOM基础结构之间 )。

下面是一些避免内存泄漏的经验法则:

使用事件系统附加事件处理程序

最常见的循环引用模式[DOM元素 - >事件处理程序 - >闭包范围 - > DOM]元素在MSDN博客文章中讨论。要避免此问题,请使用经过良好测试的事件系统之一来附加事件处理程序,例如Google doctype,Dojo 或 JQuery 中的事件处理程序。

此外,使用内联事件处理程序可能导致在IE中的另一种类型的泄漏。这不是常见的循环引用类型泄漏,而是内部临时匿名脚本对象的泄漏。有关详细信息,请参阅“DOM插入顺序泄漏模型”一节在了解和解决Internet Explorer漏洞模式和一个例子在这个JavaScript工具包教程。

避免使用expando属性

Expando属性是DOM元素的任意JavaScript属性,是循环引用的常见来源。你可以使用expando属性而不引入内存泄漏,但是很容易偶然引入。这里的泄漏模式是[DOM元素 - >通过expando - >中间对象 - > DOM元素]。最好的办法是避免使用它们。如果您确实使用它们,则只能使用带有基本类型的值。如果确实使用非原始值,则在不再需要expando属性时将其取消。请参阅了解和解决Internet Explorer泄漏模式中的“循环引用”一节。

https://zhuanlan.zhihu.com/p/24884853

定义类方法

以下是低效的,因为每次构建baz.Bar的实例时,都会为foo创建一个新函数和闭包:

baz.Bar = function() {
  // constructor body
  this.foo = function() {
    // method body
  };
}

首选方法是:

baz.Bar = function() {
  // constructor body
};

baz.Bar.prototype.foo = function() {
// method body
};

使用这种方法,无论构建多少个baz.Bar实例,都只会为foo创建一个函数,并且不会创建闭包。

初始化实例变量

将实例变量声明/初始化放在具有值类型(而不是引用类型)初始值的实例变量的原型上(i.e. values of type number, Boolean, null, undefined, or string)

(即, 类型是 number, Boolean, null, undefined, 或 string的值)

ES 6: Symbol ???

这避免了每次调用构造函数时不必要地运行初始化代码。(对于初始值依赖于构造函数的参数的实例变量,或者构造时的某个其他状态,不能这样做。)

例如,代替

foo.Bar = function() {
  this.prop1_ = 4;
  this.prop2_ = true;
  this.prop3_ = [];
  this.prop4_ = 'blah';
};

使用:


foo.Bar = function() {
  this.prop3_ = [];
};
foo.Bar.prototype.prop1_ = 4;
foo.Bar.prototype.prop2_ = true;
foo.Bar.prototype.prop4_ = 'blah';

避免闭包的陷阱

闭包是JavaScript的一个强大而有用的特性;然而,它们有几个缺点,包括:

  • 它们是内存泄漏的最常见的来源。
  • 创建闭包比创建没有闭包的内部函数慢得多,并且比重用静态函数慢得多。

例如:

function setupAlertTimeout() {
  var msg = 'Message to alert';
  window.setTimeout(function() { alert(msg); }, 100);
}

慢于:

function setupAlertTimeout() {
  window.setTimeout(function() {
    var msg = 'Message to alert';
    alert(msg);
  }, 100);
}

其慢于:

function alertMsg() {
  var msg = 'Message to alert';
  alert(msg);
}

function setupAlertTimeout() {
window.setTimeout(alertMsg, 100);
}

它们向作用域链添加级别。当浏览器解析属性时,必须检查作用域链的每个级别。在以下示例中:

var a = 'a';

function createFunctionWithClosure() {
var b = 'b';
return function () {
var c = 'c';
a;
b;
c;
};
}

var f = createFunctionWithClosure();
f();

当调用f时,引用a比引用b慢,这比引用c慢。

有关何时使用闭包与IE的信息的, 请参阅IE + JScript性能建议第3部分:JavaScript代码效率低下

避免使用 with

避免在代码中使用 with 。它对性能有负面影响,因为它修改了作用域链,使得在其他作用域中查找变量更加昂贵。

Avoiding browser memory leaks

内存泄漏是Web应用程序的一个常见的问题,可能导致巨大的性能损失。随着浏览器的内存使用量的增长,您的Web应用程序以及用户系统的其余部分会减慢。


Web应用程序最常见的内存泄漏包括JavaScript脚本引擎和浏览器的C ++对象实现DOM之间的循环引用 ( 例如JavaScript脚本引擎和Internet Explorer的COM基础结构之间,或JavaScript引擎和Firefox XPCOM基础结构之间 )。


下面是一些避免内存泄漏的经验法则:

使用事件系统附加事件处理程序

最常见的循环引用模式[DOM元素 - >事件处理程序 - >闭包范围 - > DOM]元素在MSDN博客文章中讨论。要避免此问题,请使用经过良好测试的事件系统之一来附加事件处理程序,例如Google doctypeDojoJQuery 中的事件处理程序。

此外,使用内联事件处理程序可能导致在IE中的另一种类型的泄漏。这不是常见的循环引用类型泄漏,而是内部临时匿名脚本对象的泄漏。有关详细信息,请参阅“DOM插入顺序泄漏模型”一节在了解和解决Internet Explorer漏洞模式和一个例子在这个JavaScript工具包教程

避免使用expando属性

Expando属性是DOM元素的任意JavaScript属性,是循环引用的常见来源。你可以使用expando属性而不引入内存泄漏,但是很容易偶然引入。这里的泄漏模式是[DOM元素 - >通过expando - >中间对象 - > DOM元素]。最好的办法是避免使用它们。如果您确实使用它们,则只能使用带有基本类型的值。如果确实使用非原始值,则在不再需要expando属性时将其取消。请参阅了解和解决Internet Explorer泄漏模式中的“循环引用”一节。

js closures All In One

setTimeout 闭包,log(i, arr[¡])

闭包的3 种实现方式

var, let, closure, IIFE

"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2020-09-30
 * @modified
 *
 * @description closures 闭包
 * @difficulty Easy
 * @complexity O(n)
 * @augments
 * @example
 * @link
 * @solutions
 *
 * @best_solutions
 *
 */

const log = console.log;

// setTimeout 闭包,log(i, arr[¡])

const arr = ["A", "B", "C"];

// var ❌
for (var i = 0; i < arr.length; i++) {
  if(i == 0) {
    log(`var bug`);
  }
  setTimeout(() => {
    log(`❌i =`, i, `arr[${i}] =`, arr[i]);
  }, 1000);
}

// IIFE ✅
for (var i = 0; i < arr.length; i++) {
  ((i) => {
    setTimeout(() => {
      if(i == 0) {
        log(`\nIIFE`);
      }
      log(`🚀i =`, i, `arr[${i}] =`, arr[i]);
    }, 1000);
  })(i);
}

// closures ✅
for (var i = 0; i < arr.length; i++) {
  function test(i) {
    setTimeout(() => {
      if(i == 0) {
        log(`\nclosures`);
      }
      log(`👍 i =`, i, `arr[${i}] =`, arr[i]);
    }, 1000);
  }
  test(i);
}

// let ✅
for (let i = 0; i < arr.length; i++) {
  setTimeout(() => {
    if(i == 0) {
      log(`\nlet`);
    }
    log(`✅i =`, i, `arr[${i}] =`, arr[i]);
  }, 1000);
}

/*

$ node closures.js

var bug
❌i = 3 arr[3] = undefined
❌i = 3 arr[3] = undefined
❌i = 3 arr[3] = undefined

IIFE
🚀i = 0 arr[0] = A
🚀i = 1 arr[1] = B
🚀i = 2 arr[2] = C

closures
👍 i = 0 arr[0] = A
👍 i = 1 arr[1] = B
👍 i = 2 arr[2] = C

let
✅i = 0 arr[0] = A
✅i = 1 arr[1] = B
✅i = 2 arr[2] = C

*/


for & log

"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2020-10-16
 * @modified
 *
 * @description for & log
 * @difficulty Easy Medium Hard
 * @complexity O(n)
 * @augments
 * @example
 * @link
 * @solutions
 *
 * @best_solutions
 *
 */

const log = console.log;

const len = 3;

for (var i = 0; i < len; i++) {
  setTimeout(() => {
    log(`❌ i =`, i);
  }, 0);
}

// ES6 let
for (let j = 0; j < len; j++) {
  setTimeout(() => {
    if(j === 0) {
      log(`\n`);
    }
    log(`✅ j =`, j);
    // if(j === len - 1) {
    //   log(`\n`);
    // }
  }, 0);
}

// IIFE
for (var k = 0; k < len; k++) {
  (function(k) {
    setTimeout(() => {
      if(k === 0) {
        log(`\n`);
      }
      log(`✅ k =`, k);
    }, 0);
  })(k);
}

// 闭包 closure
for (var l = 0; l < len; l++) {
  function test(l) {
    setTimeout(() => {
      if(l === 0) {
        log(`\n`);
      }
      log(`✅ l =`, l);
    }, 0);
  }
  test(l);
}


/*

$ node for-var-closures.js

❌ i = 3
❌ i = 3
❌ i = 3

✅ j = 0
✅ j = 1
✅ j = 2

✅ k = 0
✅ k = 1
✅ k = 2

✅ l = 0
✅ l = 1
✅ l = 2

*/


闭包怎么释放内存

  1. 引用为零, ref=null

https://segmentfault.com/q/1010000020309203

(🐞 反爬虫测试!打击盗版⚠️)如果你看到这个信息, 说明这是一篇剽窃的文章,请访问 https://www.cnblogs.com/xgqfrms/ 查看原创文章!

refs



©xgqfrms 2012-2021

www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!

原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2017-01-15 00:01  xgqfrms  阅读(86)  评论(4编辑  收藏  举报