`
七七八八
  • 浏览: 46218 次
社区版块
存档分类
最新评论

[JavaScript]项目优化总结

阅读更多

前端时间对公司已有项目JavaScript代码进行优化,本文的是对优化工作的一个总结,拿出来与大家分享。当然我的优化方式可能并不是最优的,或者说有些不对的地方,请指教。

目录

JavaScript优化总结分为以下几点

模块化(类编程)

静态类

实例类

JavaScript压缩/合并

Uglifyjs安装

UglifyJS使用

JavaScript文件合并

文档生成

YUIDoc安装与使用

YUIDoc标签

公共类库说明

目录结构

自动合并、压缩脚本

文档说明

参考链接、进一步阅读

 

 

JavaScript优化总结分为以下几点

优化前后对比

优化前

优化后

代码混乱,同样功能的函数重复出现在多个地方。如果需要修改实现,需要找到所有的地方。牵一发而动全身

模块化,提取公共接口组织为库、结构清晰、方便代码重用、并且能够游戏防止变量污染问题。

JavaScript文件未压缩,size比较大加载消耗网络耗时,阻塞页面渲染

 

JavaScript公共库文件使用UglifyJS压缩:

n  Size比较小优化了网络加载时间

n  压缩混淆了代码,在一定程度上保护代码

使用时需要加载多个单独的JavaScript文件,增加了http请求数降低性能

对公共库合并压缩在减少size的同时,减少http请求数

缺乏文档(让后面的开发者对已有功能不清楚,这在一定程度上造成前面说的,同样功能的函数重复出现在多个地方)

公共库中每个类、函数、属性都有说明文档

 

 

l  模块化(类编程):代码清晰、有效防止变量污染问题、代码重用方便扩展等;

l  JavaScript压缩混淆:减少size优化加载时间,混淆保护代码;

l  JavaScript文件合并:减少http请求优化网络耗时提升性能;

l  生成文档:方便公共库的使用,查找接口方便。

 

对于静态类来说JavaScript实现比较简单,使用Object直接量就已经够用了;但是要创建实例化、可继承经典的类需要做一番工作。因为JavaScript基于原型的(prototype-based编程语言,并没有包含内置类的实现(它没有访问控制符,它没有定义类的关键字class,它没有支持继承的extend或冒号,它也没有用来支持虚函数的virtual等),但是我们通过JavaScript可以轻易地模拟出经典的类。

根据宝宝JS公共接口的特性,它们不需要实例化,所以优化使用了该方式。下面以PetConfigParser为例介绍下实现方式:

PetConfigParser

var PetConfigParser;

if (!PetConfigParser) {

    PetConfigParser = {};

}

 

(function () {

    //private 变量、函数

    /**

     宝宝所有配置字典,以【cate * 10000 + (lvl - 1) * 10 + dex - 1】为key

     * @attribute    petDic

     * @type {Object}

     * @private

     */

    var petDic = null;  //宝宝字典

 

    /**

     根据__pet_config构建一个Object字典,以catedexlvl组合作为key

     * @method buildPetDic

     * @private

     * @return {void}

     */

    function buildPetDic() {

        petDic = new Object();

        for (var item in __pet_config) {

            var lvl = parseInt(__pet_config[item]['lvl']);

            var dex = parseInt(__pet_config[item]['dex']);

            var cate = parseInt(__pet_config[item]['cate']);

            var key = cate * 10000 + (lvl - 1) * 10 + dex;

            petDic[key] = __pet_config[item];

        }

    }

 

    //public 接口

 

    /**

     根据宝宝id,读取__pet_config中对应宝宝的信息

     * @method getPetById

     * @param   {String/int} petId 宝宝id

     * @return  {Object} pet 宝宝的所有静态信息,如{id:"300003289", lvl:"1", dex:"2", price:"200", life:"2592000", cate:"3", name:"飞天小使等级1熟练2", intro:"", skill:"护身符", skill1_prob:"30", skill2_prob:"0"}

     */

    if (typeof PetConfigParser.getPetById !== 'function') {

        PetConfigParser.getPetById = function (petId) {

            var pet = ("undefined" == typeof (__pet_config)) ? null : __pet_config["pet_" + petId];

            return pet;

        }

}

})();

 

这种方式利用了JavaScript匿名函数来创建私有作用域,这些私有作用域只能在内部访问。总结上述过程分为以下几个步骤:

1)        定义一个全局的变量(var PetConfigParser),注意变量首字母大写与普通变量区别;

2)        然后创建一个匿名函数并运行( (function () {/*xxxx*/ })(); ),在匿名函数内部创建局部变量和函数,它们只能在当前作用域中被访问到;

3)        全局变量(var PetConfigParser)可以在任何地方访问到,在匿名函数内部操作PetConfigParser添加静态函数。

使用实例

$(function () {

        DialogManager.init();

        $('#showDialog').click(function () {

            DialogManager.show("#msgBoxTest", "#closeId");

            return false;

        });

 

        $('#cofirmBtn').click(function () {

            DialogManager.hide();

            return false;

        });

})

JavaScript实现经典的类,总结有三种方法:

n  构造函数方式;

n  原型方式;

n  构造函数+原型的混合方式

构造函数方式

构造函数用来初始化实例对象的属性和值。任何JavaScript函数都可以用作构造函数,构造函数必须使用new运算符作为前缀来创建新的实例。

构造函数方式

var Person = function (name) {

    this.name = name;

    this.sayName = function(){

        alert(this.name);

    };

}

 

//实例化

var tyler = new Person("tylerzhu");

var saylor = new Person("saylorzhu");

tyler.sayName();

saylor.sayName();

//检查实例

alert(tyler instanceof Person);

构造函数方式跟传统的面向对象语言是不是很相识!只不过是class关键字用function替换了。

注意:不要省略new否则Person(“tylerzhu”) //==>undefined。当使用new关键字来调用构造函数时,执行上下文(context)从全局对象(window)变成一个空的上下文,这个上下文代表了新生成的实例。因此,this关键子指向当前创建的实例。所以省略new时,没有进行上下文切换会在全局对象中查找name,没有找到而创建一个全局变量name返回undefined

原型方式

构造函数方式简单,但是存在一个浪费内存的问题。如上面的例子中实例化了两个对象tylersaylor,表面上好像没什么问题,但是实际上对于每一个实例对象,sayName()方法都是一模一样的内容,每一次生成一个实例,都必须为重复的内容申请内容。

alert(tyler. sayName == saylor. sayName) 输出false!!!

Javascript中每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例共享

原型方式

var Person = function (name) {

    Person.prototype = name;

    Person.prototype.sayName = function(){

        alert(this.name);

    }

}

 

//实例化

var tyler = new Person("tylerzhu");

var saylor = new Person("saylorzhu");

tyler.sayName();

saylor.sayName();

 

//检查实例

alert(tyler instanceof Person);

这时tylersaylor实例的sayName方法,都是同一个内存地址(指向prototype对象),因此原型方法更节省内存。

但是看tyler.sayName();saylor.sayName();两者输出,会看出问题 —— 它们都输出“saylorzhu”。因为原型所有属性都共享,只要一个实例改变其他的都会跟着改变,所以实例化对象saylor覆盖了tyler

 

构造函数+原型的混合方式

构造函数方式可以为同一个类的每一个对象分配不同的内存,这很适合写类的时候设置属性;但是设置方法的时候我们就需要让同一个类的不同对象共享同一个内存了,写方法用原型的方式最好。所以写类的时候需要把构造方法和原型两种方式混合着用(很多类库提供的创建类的方法或框架的写类方式本质上都是:构造函数+原型)。

构造函数+原型

var Person = function (name) {

    Person.prototype = name;

    Person.prototype.sayName = function(){

        alert(this.name);

    }

}

 

//实例化

var tyler = new Person("tylerzhu");

var saylor = new Person("saylorzhu");

tyler.sayName();

saylor.sayName();

//检查实例

alert(tyler instanceof Person);

这样即可通过构造函数构造不同name的人,对象实例也都共享sayName方法,不会造成内存浪费。

JavaScript压缩/合并

JavaScript代码压缩混淆的意义:简单的说就是为了减小js文件大小,去掉多余的注释和换行缩进等,使得下载起来更快,提高用户体验

JavaScript压缩工具有很多,我推荐使用jQuery现在使用的工具UglifyJSjQuery以前也使用过多种压缩工具,如Packer),因为它压缩性能很好。

jQuery 1.5 发布的时候 john resig 大神说所用的代码优化程序从Google Closure切换到UglifyJS,新工具的压缩效果非常令人满意”

下面是官方性能对比:We’re still a lot better than YUI in terms of compression, though slightly slower. We’re still a lot faster than Closure, and compression after gzip is comparable.

File

UglifyJS

UglifyJS

+gzip

Closure

Closure

+gzip

YUI

YUI

+gzip

jquery-1.6.2.js

91001

(0:01.59)

31896

90678

(0:07.40)

31979

101527

(0:01.82)

34646

paper.js

142023

(0:01.65)

43334

134301

(0:07.42)

42495

173383

(0:01.58)

48785

prototype.js

88544

(0:01.09)

26680

86955

(0:06.97)

26326

92130

(0:00.79)

28624

thelib-full.js

251939

(0:02.55)

72535

249911

(0:09.05)

72696

258869

(0:01.94)

76584

 

Uglifyjs安装

UglifyJS是基于 NodeJS Javascript语法解析/压缩/格式化工具,所以我们要安装NodeJS

N ode.js is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.

JavaScript最早是运行在浏览器中,然而浏览器只是提供了一个上下文,它定义了使用JavaScript可以做什么,但并没有“说”太多关于JavaScript语言本身可以做什么。事实上,JavaScript是一门“完整”的语言: 它可以使用在不同的上下文中,其能力与其他同类语言相比有过之而无不及。Node.js事实上就是另外一种上下文,它允许在后端(脱离浏览器环境)运行JavaScript代码。

要实现在后台运行JavaScript代码,代码需要先被解释然后正确的执行。Node.js的原理正是如此,它使用了GoogleV8虚拟机(GoogleChrome浏览器使用的JavaScript执行环境),来解释和执行JavaScript代码。

除此之外,伴随着Node.js的还有许多有用的模块,它们可以简化很多重复的劳作,比如向终端输出字符串。因此,Node.js事实上既是一个运行时环境,同时又是一个库。

l  Windows下面直接下载exe文件执行即可。(http://nodejs.org/

C:\Users\tyler>node -v

v0.8.2

l  设置代理(公司网络不设置代理无法下载,外网环境不需要)

npm,全称是"node packagemanager",它是node包管理器,第三方的package全是通过npm去安装的。”

n  npm设在代理

npm config set proxy=http://proxy.tencent.com:8080

n  npm默认选择http方式,不选用https

npm config set registry http://registry.npmjs.org

l  npm安装uglify-js

npm –g install uglify-js

l  验证安装是否成功

C:\Users\tyler>npm -v

1.1.36

UglifyJS使用

uglifyjs [ 选项... ] [ 文件 ]

文件参数应该放在选项后面,uglifyjs 会读取文件中的javascript代码进行处理。如果你不指定输出的文件名,那么他会把处理后的内容输出到命令行中。

支持的选项 

l  -b  --beautify - 输出格式化代码,当传入该参数,下面的附加选项用于更美观的控制格式化:

n  -i N  --indent N - 缩进级别(空格数量)

n  -q  --quote-keys - 是否用引号引起字符串对象的键(默认只会引起不能被正确标志的键名)

l  --ascii -默认 UglifyJS 不处理字符编码而直接输出 Unicode 字符,通过传入该参数将非ASCII编码的字符转化为\cXXXX的序列(输出总按照UTF8编码,但传入该选项能得到ASCII编码的输出)。

l  -nm  --no-mangle - 不改变变量名称

l  -ns  --no-squeeze - 不调用 ast_squeeze() 函数(该函数会做多种优化使得结果更小,可读性略有降低)

l  -mt  --mangle-toplevel - 在顶级作用域打乱变量名称(默认不开启)

l  --no-seqs - 当调用 ast_squeeze() 将会合并多个语句块为一个语句块,如 "a=10; b=20; foo()" 将被转换为 "a=10,b=20,foo()"

l  --no-dead-code - 默认 UglifyJS 将会删除不被用到的代码,传入该参数禁用此功能。

l  -nc  --no-copyright - 默认 uglifyjs 会在输出后的代码中添加版权信息等注释代码,传入该参数禁用此功能。

l  -o 文件名  --output 文件名 - 指定输出文件名,如果不指定,则打印到标准输出(STDOUT

l  --overwrite - 如果传入的JS代码来自文件而不是标准输入,传入该参数,输出会覆盖该文件。

l  --ast - 传入该参数会得到抽象的语法树而不是Javascript,对调试或了解内部代码很有用。

l  -v  --verbose - 在标准错误输出一些信息(目前的版本仅输出操作用时)

l  --extra - 开启附加优化,这些优化并未得到全面的测试。

l  --unsafe - 开启其他附加优化,这些优化已知在特定情况下并不安全,目前仅支持:

l  foo.toString() ==> foo+””

l  --max-line-len (默认32K字节) - 32K字节出增加换行符,传入0禁用此功能。

l  --reserved-names - 一些类库会依赖一些变量,该参数指定的名称不会被混淆掉,多个用逗号隔开

下面是我们使用uglifyjs压缩,PetConfigParser.js的例子:

uglifyjs -nc -mt PetConfigParser.js > PetConfigParser.min.js

PetConfigParser.js压缩前后对比

压缩前

clip_image002

压缩后

clip_image003

JavaScript文件合并

规则1——减少HTTP请求(Minimize HTTP Requests

Yahoo前端优化性能规则[5]

只有10%20%的最终用户响应时间花在接收请求的HTML文档上,剩下的80%90%时间都花在HTML文档所引用的所有组件(图片、脚本、样式表、Flash等)进行的HTTP请求上。因此,改善响应时间最简单的办法就是减少组件数量并由此减少HTTP请求数。

对公共库合并压缩在减少size的同时,减少http请求优化网络耗时提升性能。

YUIDoc 是一个基于 Node.js 的应用程序,用来根据 JavaScript 的注释中生成 API 文档,类似 JavaDocASDoc,这也是当前 YUI 用来生成文档的工具。

YUIDoc安装与使用

l  YUIDoc安装

UglifyJS一样,YUIDoc也是基于Nodejs的一个应用程序,使用npm安装即可。

npm -g install yuidocjs.

校验安装是否成功

C:\Users\tyler>yuidoc -v

0.3.15

l  生成文档(一次性生成)

yuidoc .

一次性生成该目录及其子目录下所有JS的文档 默认在不配置的情况下会生成在当前目录的out目录中。

-o, --out <directory path> Path to put the generated files (defaults to ./out)

l  生成文档(实时生成)

YUIDoc还提供了一种实时文档生成的方式,有利于团队协作开发 比如在SVN上部署YUIDoc实时文档,递交到SVN的代码都会及时生成文档提供团队使用查阅

yuidoc --server

默认开放监听当前目录文件变动,开放3000端口 可以通过

http://127.0.0.1:3000/

来访问文档 如果3000端口被占用,也可以指定特定端口号

yuidoc --server 5000

来通过开放5000端口提供文档访问

YUIDoc标签

要使用YUIDoc,那么所有注释都得安装YUIDoc的标准来,否则不能正确解析出文档。YUIDoc使用的标签和其它语言类同,比较容易理解。下面不详细说明每个标签,只列举几个例子,具体可参加官方文档。例如:

PetConfigParser类进行注释:

/**

 宝宝配置文件解析,及提供查询宝宝配置相关的操作方法<br/>

 * 1. getPetById 根据宝宝id获取对应宝宝的信息<br/>

 * 2. getPetName 根据宝宝的id,读取宝宝信息,然后拼接出宝宝的名字,如3+10天蝎宝宝<br/>

 等等<br/>

 * @author tylerzhu

 * @class PetConfigParser

 * @static

 */

对类中的变量进行注释:

    /**

     宝宝所有配置字典,以【cate * 10000 + (lvl - 1) * 10 + dex - 1】为key

     * @attribute    petDic

     * @type {Object}

     * @private

     */

对类中函数进行注释:

/**

     根据宝宝id,读取__pet_config中对应宝宝的信息

     * @method getPetById

     * @param   {String/int} petId 宝宝id

     * @return  {Object} pet 宝宝的所有静态信息,如{id:"300003289", lvl:"1", dex:"2", price:"200", life:"2592000", cate:"3", name:"飞天小使等级1熟练2", intro:"", skill:"护身符", skill1_prob:"30", skill2_prob:"0"}

     */

默认生成的文档样式如下:

clip_image005

参考链接、进一步阅读

[1]      NodeJShttp://nodejs.org/

[2]      UglifyJShttps://github.com/mishoo/UglifyJS/

[3]      UglifyJS解析/压缩/格式化你的Javascripthttp://goo.gl/bwf8U

[4]      Yahoo前端优化性能规则,http://goo.gl/nfEBg

[5]      YUIDoc文档化JavaScript代码,http://goo.gl/5RJxn

[6]      YUIDoc官方,http://yui.github.com/yuidoc/


4
9
分享到:
评论
3 楼 babydeed 2012-08-15  
写的不错 赞一个
2 楼 long502147 2012-08-15  
构造函数+原型
var Person = function (name) {

    Person.prototype = name;

    Person.prototype.sayName = function(){

        alert(this.name);

    }

}

 

//实例化

var tyler = new Person("tylerzhu");

var saylor = new Person("saylorzhu");

tyler.sayName();

saylor.sayName();

//检查实例

alert(tyler instanceof Person);


这里的 Person.prototype = name; 是不是应该 改为this.name = name; ?
1 楼 lxy2330 2012-08-15  
写的很好啊!收藏起来

相关推荐

    javascript项目优化总结.docx

    综上所述,JavaScript项目优化是一个多方面、多层次的过程,涉及到代码组织、文件管理、性能提升和代码可读性等多个方面。通过合理地应用这些优化策略,可以打造出高效、稳定且易于维护的JavaScript应用程序。

    javascript项目优化总结.pdf

    以上是JavaScript项目优化的一些关键点,通过这些方法可以显著提高代码的运行效率,减少资源消耗,提升应用程序的整体性能。在实际项目中,还应注意持续监控和调整,以适应不断变化的需求和技术环境。

    JavaScript项目优化总结

    JavaScript优化总结分为以下几点优化前后对比代码混乱,同样功能的函数重复出现在多个地方。如果需要修改实现,需要找到所有的地方。牵一发而动全身模块化,提取公共接口组织为库、结构清晰、方便代码重用、并且能够...

    JavaScript必看全面总结.zip

    15. **框架与库**:如React、Vue、Angular等,它们如何简化前端开发,以及如何结合JavaScript进行实际项目开发。 这份“JavaScript必看全面总结.pdf”文档应该详细涵盖了以上所有内容,对于初学者和进阶者都是宝贵...

    javascript代码优化的8点总结

    以下是根据给定文件内容总结的关于JavaScript代码优化的8点要点。 1. 松耦合原则 松耦合是一种设计原则,指的是在修改一个组件(模块、函数、类)时,不需要改变其他组件。在JavaScript开发中,我们应该避免过度...

    JavaScript性能优化技巧分享共8页.pdf.zip

    这份"JavaScript性能优化技巧分享共8页.pdf.zip"压缩包文件很可能是对一些关键优化策略的总结,虽然我们无法直接查看具体内容,但根据标题和标签,我们可以探讨一些常见的JavaScript性能优化方法。 1. **延迟加载...

    高职《JavaScript网页开发》课程优化方案探究.pdf

    从高职《JavaScript网页开发》课程优化方案探究中,我们可以总结出以下几个知识点: 1. 课程优化的重要性:在高职教育中,课程优化是提高教学质量和学生职业能力的关键。通过对《JavaScript网页开发》课程的优化,...

    JavaScript执行效率优化及内存管理优化.docx

    总结,JavaScript执行效率优化主要包括DOM操作优化、字符串操作优化以及内存管理。通过合理利用这些技巧,可以显著提升网页的加载速度和响应性,为用户提供更好的体验。在实际开发中,应根据项目需求和浏览器兼容性...

    浅析JavaScript异步代码优化

    总结来说,优化JavaScript异步代码的关键在于减少回调地狱,提高代码可读性和可维护性。Promise、async/await等技术提供了优雅的解决方案,让异步编程更加简洁和直观。通过理解和掌握这些技术,开发者可以写出更高...

    有缘网—网站优化方案(项目总结)20141211.zip

    "有缘网—网站优化方案(项目总结)20141211.ppt"文件很可能包含项目的详细执行过程、遇到的问题、解决方案以及优化后的成果展示。这是一份宝贵的实践经验和教训总结,对于后续的优化工作具有极高的参考价值。 五、...

    javascript效果经典大总结.rar

    "javascript效果经典大总结.rar"这个压缩包文件很可能是包含了一系列JavaScript实现的经典效果示例,旨在帮助开发者提升技能和理解JavaScript在实际项目中的应用。 1. **DOM操作**:JavaScript的核心功能之一就是对...

    各个项目后的总结 -javasript集锦

    这些是所有JavaScript项目的核心,不论特效如何复杂,都需要扎实的基础知识作为支撑。 2. **DOM操作**:文档对象模型(DOM)是HTML和XML文档的编程接口。JavaScript通过DOM可以查找、修改、添加或删除页面元素,...

    JavaScript开发-自动优化Nuxtjs项目中使用的图像JPEGPNGSVGWebP和GIF

    总结来说,通过选择合适的Nuxt.js插件和配置,结合动态导入和条件加载策略,我们可以有效地优化Nuxt.js项目中的JPEG、PNG、SVG、WebP和GIF图像。这不仅能提高网站性能,也有利于提升用户的浏览体验。在实际开发中,...

    Ext性能优化总结

    ### Ext性能优化总结 在多年的Ext项目开发过程中,积累了丰富的经验与技巧,下面将这些关键的知识点进行详细的阐述,希望能为同行提供有价值的参考。 #### 一、架构优化:One Page One Application模式 在传统的...

    JavaScript结课大作业.zip

    这个项目可能涵盖了JavaScript的核心概念和高级特性,如DOM操作、事件处理、AJAX异步请求、函数式编程以及面向对象编程等。 DOM(Document Object Model)是JavaScript操作HTML和XML文档的标准接口,通过它可以动态...

    性能优化,前端,优化总结

    性能优化是前端开发中不可或缺的一部分,它直接影响到用户的体验,进而...性能优化是一个持续的过程,需要结合实际项目不断调整和优化。通过以上方法,我们可以有效地提升前端性能,为用户提供更流畅、快速的浏览体验。

    javascript实训

    总结来说,JavaScript实训涵盖了语言基础、DOM操作、事件处理、异步通信、高级特性等多个方面,这些都是成为一个合格的前端开发者所必须掌握的知识。通过实践,你可以更好地理解和运用这些知识点,为你的IT职业生涯...

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

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

    JavaScript超级玛丽

    JavaScript超级玛丽是一款基于...总之,JavaScript超级玛丽项目是一个综合展示JavaScript编程技巧、HTML5 Canvas图形绘制能力、游戏开发逻辑和优化策略的实例,对于学习和理解Web游戏开发具有很高的参考价值。

Global site tag (gtag.js) - Google Analytics