`
jy00509336
  • 浏览: 243541 次
  • 性别: Icon_minigender_1
  • 来自: 山西
社区版块
存档分类
最新评论

优化 JavaScript 代码

阅读更多

来自 Google Code 上 Let's make the web faster 项目的文章.
主要讨论了 JS 代码编码时的一些优化技巧.

其他更多内容见 http://code.google.com/speed/

 

优化 JavaScript 代码

作者: Gregory Baker, GMail 软件工程师 和 Erik Arvidsson, Google Chrome 软件工程师

需要的经验: JavaScript 相关工作知识

客户端脚本能让你的应用更加地动态和活跃, 但是浏览器对代码 的解析可能造成效率问题, 而这种性能差异在客户端之间也不尽相同. 这里我们讨论和给出一些优化你的 JavaScript 代码的提示和最佳实践.

使用字符串

字符串连接操作会对 Internet Explorer 6 和 7 的垃圾收集带来很大的影响. 尽管这个问题在 Internet Explorer 8 里面得到解决 -- 字符串连接在 IE8 和其它非 IE 浏览器(如 Chrome)中稍微更有效率一点 -- 如果你的用户中有很大一部分在使用 Internet Explorer 6 或 7, 你就需要非常注意你构建字符串的方式了.

有如下示例代码 :

var veryLongMessage =
'This is a long string that due to our strict line length limit of' +
maxCharsPerLine +
' characters per line must be wrapped. ' +
percentWhoDislike +
'% of engineers dislike this rule. The line length limit is for ' +
' style purposes, but we don't want it to have a performance impact.' +
' So the question is how should we do the wrapping?';

比起用连接的方式, 尝试使用 join():

var veryLongMessage =
['This is a long string that due to our strict line length limit of',
maxCharsPerLine,
' characters per line must be wrapped. ',
percentWhoDislike,
'% of engineers dislike this rule. The line length limit is for ',
' style purposes, but we don't want it to have a performance impact.',
' So the question is how should we do the wrapping?'
].join();

相似的, 用连接的方式在条件语句和循环中构建字符串是很低效的. 错误的方式:

var fibonacciStr = '前 20 个斐波那契数 ';
for (var i = 0; i < 20; i++) {
fibonacciStr += i + ' = ' + fibonacci(i) + '
';
}

正确的方法:

var strBuilder = ['前 20 个斐波那契数:'];
for (var i = 0; i < 20; i++) {
  strBuilder.push(i, ' = ', fibonacci(i));
}
var fibonacciStr = strBuilder.join('');

构建通过辅助函数生成的字符串

通过传递字符串构建器(可以是数组或者辅助类)到函数中构建长字符串, 以避免出现存放临时结果的字符串.

例如, 假定 buildMenuItemHtml_ 需要用文字串和变量构建一个字符串, 并且会在内部使用一个字符串构建器, 与其使用:

var strBuilder = [];
for (var i = 0; i < menuItems.length; i++) {
  strBuilder.push(this.buildMenuItemHtml_(menuItems[i]));
}
var menuHtml = strBuilder.join();

不如用:

var strBuilder = [];
for (var i = 0; i < menuItems.length; i++) {
  this.buildMenuItem_(menuItems[i], strBuilder);
}
var menuHtml = strBuilder.join();

定义类的方法

下面的代码 效率不高, 因为每次构造 baz.Bar 的实例时, 都会为 foo 创建一个新函数和闭包(closure):

baz.Bar = function() {
  // 构造函数代码
  this.foo = function() {
  // 方法代码
  };
}

推荐的方式为:

baz.Bar = function() {
  // 构造函数代码
};

baz.Bar.prototype.foo = function() {
  // 方法代码
};

用这种方式, 无论构造了多少个 baz.Bar 实例, 只会创建一个函数给 foo , 同时不会创建任何闭包.

初始化实例变量

将带有值类型(非引用的)的初始化值(例如类型为数字, 布尔值, null, undefined 或字符串的值)的变量声明/初始化代码 直接放在 prototype 原型中. 这可以避免每次调用构造函数时不必要地运行初始化代码. (这个方法无法应用到初始化值由构造器参数决定或构造时状态不确定的实例变量上.)

例如, 比起写:

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';

谨慎地使用闭包(closure)

闭包是 JavaScript 中一个强大而有用的特性; 但是, 它们也有不好的地方, 包括:

  • 它们是最常见的内存泄漏源头.
  • 创建一个闭包比创建一个没有闭包的内联函数明显要慢, 比起重用一个静态函数则更慢. 例如:

    function setupAlertTimeout() {
      var msg = '要显示的消息';
      window.setTimeout(function() { alert(msg); }, 100);
    }

    比下面的代码 慢:

    function setupAlertTimeout() {
      window.setTimeout(function() {
        var msg = '要显示的消息';
        alert(msg);
      }, 100);
    }

    更比下面的代码 慢:

    function alertMsg() {
      var msg = '要显示的消息';
      alert(msg);
    }

    function setupAlertTimeout() {
      window.setTimeout(alertMsg, 100);
    }
  • 他们增加了作用域链(scope chain)的层级. 当浏览器解析属性时, 作用域链的每一个层级都必须被检查一次. 在下面的例子中:

    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+JScript Performance Recommendations Part 3: JavaScript Code inefficiencies 获得更多有关在 IE 中使用闭包的信息.

避免使用 with

在你的代码 中避免使用 with . 它对性能有非常坏的影响, 因为它修改了作用域链, 让查找在其它作用域的变量变得代价高昂.

避免浏览器内存泄漏

内存泄漏对 Web 应用而言是个很普遍的问题, 它会带来严重的性能问题. 当浏览器的内存使用上升时, 你的 Web 应用, 连同用户系统的其他部分, 都会变慢. Web 应用最常见的内存泄漏原因是: 在 JavaScript 脚本引擎和浏览器 DOM 的 C++ 对象实现间的循环引用(例如, 在 JavaScript 脚本引擎和 Internet Explorer 的 COM 基础架构间, 或者 JavaScript 引擎和 Firefox 的 XPCOM 基础架构间).

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

使用一个事件系统来附加事件处理函数

最常见的循环引用模式 [ DOM 元素 --> 事件处理函数 --> 闭包作用域 --> DOM ] 在 这篇 MSDN 的 Blog 文章中讨论过了. 为避免这个问题, 可以使用一个经过严格测试的事件系统来附件事件处理函数, 例如 Google doctype , Dojo , or JQuery .

另外, 在 IE 中使用内联(inline)的事件处理函数会导致另外一类泄漏. 这不是通常的循环引用泄漏, 而是内存中临时匿名脚本对象的泄漏. 详情请查看 理解和解决 IE 泄漏模式(Understanding and Solving Internet Explorer Leak Patterns) 的 "DOM 插入顺序泄漏模型(DOM Insertion Order Leak Model)" 一节, 另外在 JavaScript Kit 教程 中还有一个例子.

避免使用扩展(expando)属性

扩展属性是附加到 DOM 元素上的任意 JavaScript 属性, 也是循环引用的常见原因. 你能够在使用扩展属性时不导致内存泄漏, 但是很容易不小心就引入一个泄漏. 这个泄漏的模式是 [ DOM 元素 --> 扩展属性 --> 中间对象 --> DOM 元素 ]. 最好的方法就是避免使用它们. 如果你要使用它们, 就只使用简单的值类型. 如果你要非简单的类型, 那么在不再需要扩展属性时将它设为空(null). 参见 理解和解决 IE 泄漏模式(Understanding and Solving Internet Explorer Leak Patterns) 中的 "循环引用(Circular References)" 一节.

分享到:
评论

相关推荐

    优化 JavaScript 代码的方法小结

    优化 JavaScript 代码 作者: Gregory Baker, GMail 软件工程师 和 Erik Arvidsson, Google Chrome 软件工程师 需要的经验: JavaScript 相关工作知识 客户端脚本能让你的应用更加地动态和活跃, 但是浏览器对代码的...

    javascript实用代码压缩工具

    "javascript实用代码压缩工具"就是这样一个帮助开发者优化JavaScript代码的工具。 JavaScript代码压缩主要有两个目的:一是去除代码中的空格、换行符和注释,这种过程称为"混淆";二是通过变量重命名、合并函数等...

    javascript经典特效---javascript代码自动生成.rar

    本资源“javascript经典特效---javascript代码自动生成.rar”显然聚焦于如何利用JavaScript生成代码,以创建出吸引人的视觉特效。这个压缩包内包含了一个名为“javascript代码自动生成.htm”的文件,很可能是教程或...

    Iroh是JavaScript的动态代码分析工具

    标题中的"Iroh是JavaScript的动态代码分析工具"表明Iroh是一个专门用于帮助开发者在运行时理解和优化JavaScript代码的工具。动态代码分析意味着它可以在程序执行过程中收集数据,而不仅仅是静态地分析源代码。这种...

    利用ClosureCompiler通过Rollup缩小和优化JavaScript

    本文将详细介绍如何结合两者来有效地缩小和优化JavaScript代码。 Closure Compiler是一款由Google开发的高级JavaScript编译器,它能够对源代码进行静态分析和优化,包括删除未使用的变量、函数和类,以及进行类型...

    JavaScript语言精粹(高清电子版)和高性能JavaScript 双语版

    这本书的重点在于优化JavaScript代码的性能,确保应用程序的高效运行。书中可能包含以下知识点: 1. **性能分析**:如何使用开发者工具进行性能测试,识别瓶颈并进行优化。 2. **数据结构和算法**:选择合适的数据...

    Sequential在浏览器中可视化JavaScript代码执行的环境

    这个创新的平台提供了一种序列化的视图,使开发者可以更深入地了解代码的每一步操作,对于学习、调试和优化JavaScript代码尤其有帮助。在本文中,我们将详细探讨Sequential的特性、工作原理以及如何利用它来提升开发...

    网站页面代码该如何做SEO优化-如何优化js代码来符合seo优化标准精编范文样本.docx

    以下是关于如何优化JavaScript代码以符合SEO优化标准的详细解释: 首先,优化HEAD部分的代码规范化至关重要。搜索引擎爬虫首先读取HEAD部分,标准化且独特的代码能够吸引搜索引擎的注意力,避免模板化的代码设计。...

    JavaScript代码优化一例.pdf

    "JavaScript代码优化一例" 本文主要讨论JavaScript代码的优化,着重于介绍JavaScript代码在企业开发中的重要性及其优化方法。 一、JavaScript代码的重要性 随着Web 2.0和Ajax概念的提出,JavaScript代码得到了...

    javascript混淆,javascript压缩,javascript加密软件

    JavaScript是Web开发中不可或缺的一部分,它为网页提供了动态交互的能力。然而,随着互联网安全问题日益凸显...在实际开发中,开发者会根据项目需求选择合适的工具和策略,如`hdjso.exe`,来保护和优化JavaScript代码。

    JavaScript征途 图书+源代码

    8. **性能优化**:优化JavaScript代码以提高网页性能也是必不可少的,包括减少DOM操作、缓存策略、事件委托等技巧。 9. **源码分析**:结合附带的源代码,读者可以更直观地理解书中理论知识的实际运用,这些源码...

    Google V8 Javascript引擎源代码

    **Google V8 JavaScript引擎**是Google为Chrome浏览器开发的一款高性能的JavaScript引擎,它以其快速的解释和...对于想要深入研究JavaScript引擎内部机制或优化JavaScript代码的开发者来说,V8源代码是一个宝贵的资源。

    JavaScript大全 常用JS效果代码

    10. **性能优化**:优化JavaScript代码以提高网页加载速度和运行效率也是开发者必须掌握的技能,包括减少HTTP请求、优化DOM操作、利用缓存等策略。 这个压缩包中的代码实例对于学习和提升JavaScript技能非常有帮助...

    Javascript的有效代码

    优化JavaScript代码可以提升用户体验。包括减少DOM操作、使用事件委托、缓存计算结果、避免全局查找、压缩和最小化代码等技巧。同时,了解V8引擎的工作原理,如即时编译(JIT)、垃圾回收等,也能帮助我们写出更高效...

    面向 Matlab 用户的 JavaScript 库 仅供学习参考用代码.rar

    因此,了解如何优化JavaScript代码以提高MATLAB应用程序的性能是非常重要的,包括减少不必要的计算、优化数据结构和利用异步编程等技巧。 9. **安全考虑**:在MATLAB中使用JavaScript时,必须注意安全性问题,因为...

    JavaScript特效代码集.rar

    10. **性能优化**:优化JavaScript代码对于提升用户体验至关重要。可能涵盖减少DOM操作、缓存引用、避免阻塞渲染等最佳实践。 总的来说,“JavaScript特效代码集”是一个学习和参考的宝贵资源,涵盖了JavaScript在...

    JavaScript_通过整理归档和脚本分析ChatGPTs代码库随时间的演变.zip

    6. 构建工具:如Webpack或Rollup,用于打包和优化JavaScript代码。 7. 开发者工作流:如持续集成/持续部署(CI/CD)流程,自动化代码测试和部署。 8. 设计模式:观察项目中使用的经典JavaScript设计模式,如工厂函数、...

    Chrome V8 Javascript引擎

    V8提供了如`--prof`和`--trace-opt`等命令行选项,帮助开发者分析和优化JavaScript代码的性能。此外,Chrome开发者工具中的Profiler面板也可以提供深入的性能剖析。 9. **跨平台兼容性**: V8设计为跨平台的,...

Global site tag (gtag.js) - Google Analytics