<编写高性能Javascript代码的N条建议_javascript技巧
您的当前位置:首页正文

编写高性能Javascript代码的N条建议_javascript技巧

2023-12-06 来源:六三科技网

多年来,Javascript一直在web应用开发中占据重要的地位,但是很多开发者往往忽视一些性能方面的知识,特别是随着计算机硬件的不断升级,开发者越发觉得Javascript性能优化的好不好对网页的执行效率影响不明显。但在某些情况下,不优化的Javascript代码必然会影响用户的体验。因此,即使在当前硬件性能已经大大提升的时代,在编写Javascript代码时,若能遵循Javascript规范和注意一些性能方面的知识,对于提升代码的可维护性和优化性能将大有好处。

下面给出编写高性能的Javascript代码的若干建议:

1、尽量不要用for-in 循环去访问数组,建议用 for 循环进行循环: 

2、建议将对象进行缓存处理,特别是DOM访问是比较消耗资源的:

3、建议不要在函数内进行过深的嵌套判断:

4、避免循环引用,防止内存泄漏:

5、建议避免在函数内返回一个未声明的变量,会污染外部变量:

6、var声明变量,建议写在多行

说明:其实单个函数时间上差别较小,这里采用循环多次用累计时间进行性能对比,不同PC配置或者浏览器测试结果可能存在差异。

以上内容是编写高性能Javascript代码的N条建议,希望对大家有所帮助。

小编还为您整理了以下内容,可能对您也有帮助:

如何编写高质量JS代码(续)_javascript技巧

继续上一篇文章《如何编写高质量JS代码》今次整理一下javascript函数知识点。

2.使用函数

函数给程序员提供了主要的抽象功能,又提供实现机制。函数可以实现其他语言中的多个不同的特性,例如,过程、方法、构造函数,甚至类或模块。

2.1 理解函数调用、方法调用以及构造函数调用之间的不同

针对面向对象编程,函数、方法和类的构造函数是三种不同的概念。

使用模式:

1,函数调用

代码如下:

function hello(username){

return "hello" + username;

}

2,方法调用

代码如下:

var obj = {

hello : function(){

return "hello , " + this.username;

},

username : "floraLam"

};

ohj.hello();//"hello , floraLam"

this变量被绑定到对象是由于hello方法被定义在obj对象中,我们也可以子啊另外一个对象中赋值一份相同的函数引用,并得到相同的答案。

代码如下:

var obj2 = {

hello : obj.hello(),

username : "floraLam"

};

3,构造函数使用

代码如下:

function User(name,passwordHash){

this.name = name;

this.passwordHash = passwordHash;

}

使用new操作符来调用User则视为构造函数。

代码如下:

var u = new User("floraLam","123");

与函数调用和方法调用不同的是,构造函数调用将一个全新的对象作为this变量的值,并隐式返回这个新对象作为调用结果。构造函数的主要职责是初始化该新对象。

2.2 熟练掌握高阶函数

高阶函数无非是那些将函数作为参数或返回值的函数,将函数作为参数(通常称为回调函数,因为高阶函数"随后调用"它)是一种特别强大、富有表现力的惯用法,也在js程序中被大量使用。

考虑数组的标准sort方法,为了对所有数组都能工作,sort方法需要调用者决定如何比较数组中的任意两个元素。

代码如下:

function compareNumber(x,y){

if(x < y){

return -1;

}

if(x > y){

return 1;

}

return 0;

}

[3,1,4,1,5,9].sort(compareNumbers);//[1,1,3,4,5,9]

代码如下:

[3,1,4,1,5,9].sort(function(x,y){

if(x < y){

return -1;

}

if(x > y){

return 1;

}

return 0;

});//[1,1,3,4,5,9]

上述例子使用一个匿名函数进一步简化。

学会使用高阶函数通常可以简化代码并消除繁琐的样板代码。简单的转换字符串数组的操作我们可以使用循环这样实现:

代码如下:

var names = ["Fred","Wilma","Pebbles"];

var upper = [];

for(var i = 0,n = names.length ;i< n;i++){

upper[i] = names[i].toUpperCase();

}

upper;//["FRED","WILMA","PEBBLES"];

使用数组便利的map方法,可以消除循环,仅仅使用一个局部函数就可以对元素的逐个转换。

代码如下:

var names = ["Fred","Wilma","Pebbles"];

var upper = names.map(function(name){

return name.toUpperCase();

});

upper;//["FRED","WILMA","PEBBLES"];

另外,例如我们想创建若干个方法创建不同的字符串,具有共同的实现逻辑,每个循环通过连接每个部分的计算结果来创建一个字符串。

代码如下:

function bulidString(n,callback){

var result = "";

for(var i = 0 ; i < n ;i++){

result += callback(i);

}

return result;

}

var alphabet = bulidString(26,function(i){

return String.fromCharCode(aIndex + i);

});

alphabet;//"abcdefghijklmnopqrxtuvwxyz";

var digits = buildString(10,function(i){ return i;})

digits;//"0123456789"

var random = buildString(9,function(){

random += String.fromCharCode(Math.floor(Math.random()*26)+aIndex

});

random;//"yefjmcef"(随机)

这样能够使得读者更清晰了解该代码能做什么,无须深入实现细节。

备注

javascript返回指定范围的随机数(m-n之间)的公式:Math.random()*(n-m)+m

同时要注意题目要求,是否要求返回正整数

2.3调用模式

调用一个函数将会暂停当前函数的执行,传递控制权与参数给新的函数。 除了声明时定义的形式参数,每个函数会接收到两个新的附加参数:this和arguments。

this是个很重要的参数,并且它的值是由调用模式决定的。

以下是JavaScript中很重要的4个调用模式:

a. 方法调用模式the method invocation pattern

b. 函数调用模式the function invocation pattern

c. 构造器调用模式the constructor invocation pattern

d. Apply调用模式the apply invocation pattern

这些模式在如何初始化关键参数this上存在差异

1. 方法调用模式the method invocation method

当函数作为对象的方法的时候,我们就叫函数为方法。当一个方法被调用的时候,this绑定到调用的对象。

代码如下:

var myObj={

val:0,

increment:function(inc){

this.val+=typeof inc ==="number"? inc:1;

},

get_val:function(){return this.val;}

}

myObj.increment();// 1

myObj["increment"](2);//3

小结:

1、通过this可取得它们所属对象的上下文的方法称为公共方法

2、当用 .或者下标表达式 来使用一个函数的时候,就是方法调用模式,this对象绑定到前面的对象。

3,一个函数可以使用this来访问对象,所以它能检索对象的值或者更改对象的值。绑定this到对象发生在调用的时候。

2. 函数调用模式the function invocation pattern

当一个函数不是一个对象的属性,那么它就是作为函数来调用的。当一个函数作为函数调用模式来调用的时候,this绑定到全局对象。这是JavaScript设计时的错误并延续了下来。

代码如下:

function add(x,y){

return x+y;

}

myObj.double=function(){

var that=this;

var helper=function(){

that.val=add(that.value,that.value);

//错误的写法可能是这样,为什么错呢?因为函数作为内部函数调用的时候,this已经绑定到了错误的对象,全局对象并没有val属性,所以返回不正确的值。

//this.val = this.val+this.val;

}

helper();

}

myObj.double();//6

3. 构造器调用模式the constructor invocation pattern

JavaScript是一门基于原型继承的语言,这意味着对象可以直接继承属性从其它的对象,该语言是无类别的。

如果在一个函数前面带上new来调用,那么将得到一个隐藏连接到该函数的prototype成员的新对象,同时this也将会绑定到该新对象。

new前缀也会改变return语句的行为。这也不是推荐的编程方式。

代码如下:

var Foo = function(status){

this.status = status;

}

Foo.prototype.get_status = function(){

return this.status;

}

//构造一个Foo实例

var myFoo = new Foo("bar");

myFoo.get_status();//"bar"

4. Apply调用模式the apply invocation pattern

因为JavaScript是一个函数式的面向对象语言,所以函数可以拥有方法。

Apply方法拥有两个参数,第一个是将绑定到this的值,第二个是参数数组,也就是说Apply方法让我们构建一个数组并用其去调用函数,即允许我们选择this的值,也允许我们选择数组的值。

代码如下:

var array = [3,4];

var sum = add.apply(null,array); // 7

var statusObj = {status:"ABCDEFG"};

Foo.prototype.pro_get_status = function(prefix){

return prefix +"-"+this.status;

}

var status = Foo.prototype.get_status.apply(statusObj);// "ABCDEFG"

var pro_status = Foo.prototype.get_status.apply(statusObj,["prefix"]);// "prefix -ABCDEFG"

通常情况下,函数或方法的接收者(级绑定到特殊关键字this的值)是由调用者的语法决定性的。特别地,方法调用语法将方法被查找对象绑定到this变量。然而,有时需要使用自定义接收者来调用函数。这时候就需要使用call方法或者bind方法自定义接收者来调用方法

2.4 使用bind方法提取具有确定接受者的方法

由于方法与值为函数的属性没有区别,因此也容易提取对象的方法并提取出函数作为回调函数直接传递给高阶函数。

但这也很容易忘记将提取出来的函数的接受着绑定到该函数被提取出的对象上。

代码如下:

var buffer = {

entries: [],

add :function(s){

this.entries.push(s);

}

}

var source = ["867","-","5309"];

source.forEach(butter.add);//error:entries is undefined

这个时候butter.add的接受者不是butter对象。函数的接收者取决于它是如何被调用的,forEach方法在全局作用域中被调用,因此forEach方法的实现使用全局对象作为默认的接收者,由于全局对象中没有entries属性,因此这段代码抛出错误。

forEach方法允许调用者提供一个可选的参数作为回调函数的接收者。

代码如下:

var source = ["867","-","5309"];

source.forEach(butter.add,butter);

但并非所有高阶函数都细心周到为使用者提供回调函数的接收者。

解决方法有两种:

1)创建一个显式地一buffer对象方法的方式调用add的封装函数。不管封装函数如何被调用,它总能确保将其参数推送到目标数组中。

代码如下:

var source = ["867","-","5309"];

source.forEach(function(s){

butter.add(s);

});

2)函数对象的bind方法需要一个接收者对象,并产生一个以该接收者对象的方法调用的方法调用原来的函数的封装函数。

代码如下:

var source = ["867","-","5309"];

source.forEach(butter.add.bind(buffer));

备注

buffer.add.bind(buffer)创建一个新函数而不是修改buffer.add函数:

buffer.add === buffer.add.bind(buffer); //false

如何改进javascript代码的性能_javascript技巧


本来在那片编写可维护性代码文章后就要总结这篇代码性能文章的,耽搁了几天,本来也是决定每天都要更新一篇文章的,因为以前欠下太多东西没总结,学过的东西没去总结真的很快就忘记了,记录一下在你脑力留下更深的印象,特别是这些可维护性代码,性能什么的,当在你脑子里形成一种习惯了,那你就牛了!这里也要给初学者一个建议:多总结你学过的东西,因为这其实也是在学习新知识! 好,进入我们的主题:如何提高JS代码的性能。


1.优化DOM交互

DOM与我们的页面紧密相关,浏览器渲染页面也就是在渲染解析后的DOM元素,DOM操作与交互要消耗大量的时间,因为它们往往需要重新渲染整个页面或者一部分。进一步说,看似细微的一些操作也可能需要花很多时间来执行,因为DOM要处理的信息非常多,因此我们应该尽可能地优化与DOM相关的操作,加快浏览器对页面的渲染!为什么有些DOM操作会影响页面性能,可以查看我写的一些关于浏览器原理的文章:

ok,优化DOM操作,我们主要有一些几种方式:

1.1 最小化现场更新

什么是DOM的现场更新:需要对DOM部分已经显示的页面的一部分的显示立即更新。但是,每一个更改,不管是插入单个字符,还是一处整个片段,都有一定的性能惩罚,因为浏览器需要重新计算无数尺寸以进行更新(相关知识请阅读:)。所以,现场更新进行的越多,代码执行所花的时间就越长,反之代码执行越快,如下:

这段代码为列表mylist添加了10个项目,没添加一个项目都要进行2次的现场更新:添加元素和添加文本节点,所以这个操作一个需要完成20个现场更新,每个更新都会损失性能,可见这样的代码运行起来是相对缓慢的。

解决的方法是使用文档碎片间接地更改DOM元素:

像这样的代码只需进行一次的现场更新。记住,当给appendChild()传入文档碎片是,只有文档碎片中的子节点才会被添加到目标元素,碎片本身不会被添加。

现在,你应该明白你用循环直接进行DOM节点的增删查改是多么对不起浏览器的事了吧 `(∩_∩)′ 。

1.2 使用 innerHTML

除了上面代码中使用的creatElement() 和 appendChild()结合的方法创建DOM元素之外,还有通过给innerHTML赋值来创建。对于小的DOM更改而言,两种方法的效率其实差不多,但对于大量的DOM节点的更改,后者要比前者快得多!为啥捏?

因为当我们给innerHTML赋值时,后台会创建一个HTML解析器,然后使用内部的DOM调用来创建DOM结构,而非基于Javascript的DOM调用,由于内部方法是编译好的而非解释执行的,所以执行代码的速度要快很多!

用innerHTML改写上面的例子:

这种方式同样也只进行了一次的现场更新,并且性能要比上一种方式要好!虽然在字符串的链接上有点性能损失。

1.3 使用事件代理/事件委托

事件处理程序为web应用提供交互能力,因此许多开发人员会不分青红皂白地向页面中添加大量的处理程序,有个问题就是一个页面上的事件处理程序数量将直接关系到页面的整体运行性能。为什么捏?

首先,事件处理程序对应至少一个函数,JS中每个函数都是对象,都会占用内存,内存中的对象越多,性能就越差。

其次,我们必须事先指定所有事件处理程序,这就导致了DOM访问次数增多,会延迟整个页面的交互就绪时间,页面响应用户操作变得相对缓慢。

所以减少事件处理程序同样也可以让我们的页面更牛畅!使用事件委托势在必得啊!

事件委托的原理其实就是事件冒泡,只指定一个事件处理程序就可以管理某一类型操作的所有事件。例如:click事件会一直冒泡到document层次,也就是说我们不必为每个元素添加事件,只需在较高的层次的元素上添加事件处理程序即可,然后利用事件对象(event)的属性或方法去判断当前点击的元素,然后做出相应的响应。这个我就不展开讲了,初学者可以自行查阅事件冒泡知识。

2.作用域很重要

说到作用域啊就很容易想到作用域链(scope chain),我们知道要搜索一个变量,所在的执行环境都要沿着这条作用域向上搜索这个变量,作用域链上有很多的变量,那么我们就得遍历,遍历就需要时间啊,而且你越往上查找所需时间越多,如果我们能减少这个时间,我们代码执行效率不是可以提高了吗?

好聪明啊,ok,我看看有哪些方式可以减少这个时间:

2.1 避免全局查找

这是性能优化的一重点,上面也说了,越往上查找时间越多,也就是说查找全局变量和函数比局部要多!看代码:

这代码很正常呀!我之前也经常这么做滴。但是我们细心可以发现,这段代码有三处引用了全局变量document,如果我们的页面很多图片,那么在for循环中的document就会被执行上百次,而每次都要需要在作用域链中查找,时间都去哪了,我还没......停!。

我们可以通过在函数中创建一个局部变量保存对document的引用,这样,我们在函数里任何地方引用document都不用跑到全局变量去找了。这样就改进了代码的性能,看代码:

所以啊,我们在开发中,如果在函数中会经常用到全局变量,把它保存在局部变量中!

2.2 避免使用with语句

用with语句延长了作用域,查找变量同样费时间,这个我们一般不会用到,所以不展开了。解决方法还是和上面的例子一样,将全局变量保存在局部变量中!

3.优化循环

循环在编程中可谓家常便饭,在js中也随处可见,循环体会反复地执行同一段代码,执行时间一直累加,所以能够对循环体的代码进行优化也可以大大减少执行时间!如何优化?四种方式。

3.1 减值迭代

我们写迭代器(循环条件)的时候一般都这样(var i = 0;i < 10;i ++),从0开始,增加到某个特定值。然而在很多情况下,如果在循环中使用减值迭代器效率更高。我测试了下,如果循环体不复杂的话,两者差不多!

3.2 简化终止条件

由于每次循环都会计算终止条件,所以必须保证它的执行尽可能地块。这里主要是避免其他DOM元素及其属性的的查找。

3.3 简化循环体

原因和上面以上的,所以在循环体内避免大量的密集的操作。

这其实和上面讲的:1.1 最小化现场更新 。是一样的优化方式。可以倒回去看看。

4.基本的算法优化

在计算机中,算法的复杂度用O表示。下面是javascript中几种常见的算法类型:

O(1) :常数,不管有多少值,执行的时间都是恒定的,比如简单值和存储在变量中的值。
O(log n):对数,总的执行时间和数量有关,但不一定要获取每一个值,如:二分法查找
O(n) :线性,总执行时间和数量直接相关,如:遍历
O(n*n) :平方,总执行时间和数量有关,每个值至少获取N次,如:插入排序
ok,有了上面的知识,我们就可以对javascript进行一些算法上的优化了。看代码:

这段代码进行了4次常量值的查找:数字5,变量value,数字10,变量sum,这段代码的算法复杂度就是O(1)。又如:

在javascript中访问数组元素也是一个O(1)操作,和简单的变量查找效率一样。再看:

要表达的是访问对象上的属性要比访问数组和变量的效率低。因为这是一个O(n)操作。你需要在对象的原型链中查找该属性,所花时间较多。

好了,看完这个是不是感觉眼前一片光明啊。其实我们前面所讲的要把经常用到的全局属性保存在一个局部变量中就是根据这个原理了,访问全局属性是一个O(n)的操作,而访问变量是一个O(1)的操作,大声告诉我,挖掘机哪家强啊!

5.最小化语句数

前面讲的优化差不多都是和精简优化语句有关的,是的,我觉得代码的质量和数量就是性能的评判标准。前面讲了一些代码质量相关的优化,这里就讲讲代码数量的优化。

5.1 精简变量声明

5.2 使用数组和对象字面量

6.其他

写累了,如有不正确的地方请指正哦,还有一些其他的优化,下次文章继续!

如何改进javascript代码的性能_javascript技巧


本来在那片编写可维护性代码文章后就要总结这篇代码性能文章的,耽搁了几天,本来也是决定每天都要更新一篇文章的,因为以前欠下太多东西没总结,学过的东西没去总结真的很快就忘记了,记录一下在你脑力留下更深的印象,特别是这些可维护性代码,性能什么的,当在你脑子里形成一种习惯了,那你就牛了!这里也要给初学者一个建议:多总结你学过的东西,因为这其实也是在学习新知识! 好,进入我们的主题:如何提高JS代码的性能。


1.优化DOM交互

DOM与我们的页面紧密相关,浏览器渲染页面也就是在渲染解析后的DOM元素,DOM操作与交互要消耗大量的时间,因为它们往往需要重新渲染整个页面或者一部分。进一步说,看似细微的一些操作也可能需要花很多时间来执行,因为DOM要处理的信息非常多,因此我们应该尽可能地优化与DOM相关的操作,加快浏览器对页面的渲染!为什么有些DOM操作会影响页面性能,可以查看我写的一些关于浏览器原理的文章:

ok,优化DOM操作,我们主要有一些几种方式:

1.1 最小化现场更新

什么是DOM的现场更新:需要对DOM部分已经显示的页面的一部分的显示立即更新。但是,每一个更改,不管是插入单个字符,还是一处整个片段,都有一定的性能惩罚,因为浏览器需要重新计算无数尺寸以进行更新(相关知识请阅读:)。所以,现场更新进行的越多,代码执行所花的时间就越长,反之代码执行越快,如下:

这段代码为列表mylist添加了10个项目,没添加一个项目都要进行2次的现场更新:添加元素和添加文本节点,所以这个操作一个需要完成20个现场更新,每个更新都会损失性能,可见这样的代码运行起来是相对缓慢的。

解决的方法是使用文档碎片间接地更改DOM元素:

像这样的代码只需进行一次的现场更新。记住,当给appendChild()传入文档碎片是,只有文档碎片中的子节点才会被添加到目标元素,碎片本身不会被添加。

现在,你应该明白你用循环直接进行DOM节点的增删查改是多么对不起浏览器的事了吧 `(∩_∩)′ 。

1.2 使用 innerHTML

除了上面代码中使用的creatElement() 和 appendChild()结合的方法创建DOM元素之外,还有通过给innerHTML赋值来创建。对于小的DOM更改而言,两种方法的效率其实差不多,但对于大量的DOM节点的更改,后者要比前者快得多!为啥捏?

因为当我们给innerHTML赋值时,后台会创建一个HTML解析器,然后使用内部的DOM调用来创建DOM结构,而非基于Javascript的DOM调用,由于内部方法是编译好的而非解释执行的,所以执行代码的速度要快很多!

用innerHTML改写上面的例子:

这种方式同样也只进行了一次的现场更新,并且性能要比上一种方式要好!虽然在字符串的链接上有点性能损失。

1.3 使用事件代理/事件委托

事件处理程序为web应用提供交互能力,因此许多开发人员会不分青红皂白地向页面中添加大量的处理程序,有个问题就是一个页面上的事件处理程序数量将直接关系到页面的整体运行性能。为什么捏?

首先,事件处理程序对应至少一个函数,JS中每个函数都是对象,都会占用内存,内存中的对象越多,性能就越差。

其次,我们必须事先指定所有事件处理程序,这就导致了DOM访问次数增多,会延迟整个页面的交互就绪时间,页面响应用户操作变得相对缓慢。

所以减少事件处理程序同样也可以让我们的页面更牛畅!使用事件委托势在必得啊!

事件委托的原理其实就是事件冒泡,只指定一个事件处理程序就可以管理某一类型操作的所有事件。例如:click事件会一直冒泡到document层次,也就是说我们不必为每个元素添加事件,只需在较高的层次的元素上添加事件处理程序即可,然后利用事件对象(event)的属性或方法去判断当前点击的元素,然后做出相应的响应。这个我就不展开讲了,初学者可以自行查阅事件冒泡知识。

2.作用域很重要

说到作用域啊就很容易想到作用域链(scope chain),我们知道要搜索一个变量,所在的执行环境都要沿着这条作用域向上搜索这个变量,作用域链上有很多的变量,那么我们就得遍历,遍历就需要时间啊,而且你越往上查找所需时间越多,如果我们能减少这个时间,我们代码执行效率不是可以提高了吗?

好聪明啊,ok,我看看有哪些方式可以减少这个时间:

2.1 避免全局查找

这是性能优化的一重点,上面也说了,越往上查找时间越多,也就是说查找全局变量和函数比局部要多!看代码:

这代码很正常呀!我之前也经常这么做滴。但是我们细心可以发现,这段代码有三处引用了全局变量document,如果我们的页面很多图片,那么在for循环中的document就会被执行上百次,而每次都要需要在作用域链中查找,时间都去哪了,我还没......停!。

我们可以通过在函数中创建一个局部变量保存对document的引用,这样,我们在函数里任何地方引用document都不用跑到全局变量去找了。这样就改进了代码的性能,看代码:

所以啊,我们在开发中,如果在函数中会经常用到全局变量,把它保存在局部变量中!

2.2 避免使用with语句

用with语句延长了作用域,查找变量同样费时间,这个我们一般不会用到,所以不展开了。解决方法还是和上面的例子一样,将全局变量保存在局部变量中!

3.优化循环

循环在编程中可谓家常便饭,在js中也随处可见,循环体会反复地执行同一段代码,执行时间一直累加,所以能够对循环体的代码进行优化也可以大大减少执行时间!如何优化?四种方式。

3.1 减值迭代

我们写迭代器(循环条件)的时候一般都这样(var i = 0;i < 10;i ++),从0开始,增加到某个特定值。然而在很多情况下,如果在循环中使用减值迭代器效率更高。我测试了下,如果循环体不复杂的话,两者差不多!

3.2 简化终止条件

由于每次循环都会计算终止条件,所以必须保证它的执行尽可能地块。这里主要是避免其他DOM元素及其属性的的查找。

3.3 简化循环体

原因和上面以上的,所以在循环体内避免大量的密集的操作。

这其实和上面讲的:1.1 最小化现场更新 。是一样的优化方式。可以倒回去看看。

4.基本的算法优化

在计算机中,算法的复杂度用O表示。下面是javascript中几种常见的算法类型:

O(1) :常数,不管有多少值,执行的时间都是恒定的,比如简单值和存储在变量中的值。
O(log n):对数,总的执行时间和数量有关,但不一定要获取每一个值,如:二分法查找
O(n) :线性,总执行时间和数量直接相关,如:遍历
O(n*n) :平方,总执行时间和数量有关,每个值至少获取N次,如:插入排序
ok,有了上面的知识,我们就可以对javascript进行一些算法上的优化了。看代码:

这段代码进行了4次常量值的查找:数字5,变量value,数字10,变量sum,这段代码的算法复杂度就是O(1)。又如:

在javascript中访问数组元素也是一个O(1)操作,和简单的变量查找效率一样。再看:

要表达的是访问对象上的属性要比访问数组和变量的效率低。因为这是一个O(n)操作。你需要在对象的原型链中查找该属性,所花时间较多。

好了,看完这个是不是感觉眼前一片光明啊。其实我们前面所讲的要把经常用到的全局属性保存在一个局部变量中就是根据这个原理了,访问全局属性是一个O(n)的操作,而访问变量是一个O(1)的操作,大声告诉我,挖掘机哪家强啊!

5.最小化语句数

前面讲的优化差不多都是和精简优化语句有关的,是的,我觉得代码的质量和数量就是性能的评判标准。前面讲了一些代码质量相关的优化,这里就讲讲代码数量的优化。

5.1 精简变量声明

5.2 使用数组和对象字面量

6.其他

写累了,如有不正确的地方请指正哦,还有一些其他的优化,下次文章继续!

如何编写高质量的Javascript代码

1、避免全局变量,因为全局变量容易发生名称上的冲突,可维护性不好。
a,使用命名空间
b,使用闭包
c,在函数内部使用var声明

2、编写可维护的代码
a.可读性
b.连续性
c.预见性
d.看起来是一个人写的
e.有文档

3、不要扩展内建的原型
  扩展原型的构造函数,可以提供一些很强大的功能,但是有时候他太强大了。
  有时候你会去扩展Object(),Array(),Fucntion()的原型方法,这样会导致可维护性的问题,因为这会让你的代码的移植性变差。其他的开发人员使用你的代码的时候,可能只需要原生的方法,并不需要额外的功能。
  另外,你添加进去的方法,如果在循环的时候没有使用hasOwnProperty方法就会被遍历出来,这会让人很迷惑。
  所以,最好还是不要扩展基本的对象。除非是下面的情况:
a.你确定在将来根据ECMAScript规范,浏览器会添加相应的原型方法,那么是可以的,你只不过是提前实现了这个功能。
b.你确定的你要实现的方法不存在–或许有时候在代码的其他的地方实现了,或者有的浏览器支持,这都是不行的。
c.有非常清晰的文档,并且与团队成员沟通过

4、避免隐藏的类型转换
  Javascript在你比较两个变量的时候会进行类型的转换,这就是为什么 false == 0或者”" == 0会返回true。
  为了避免这种隐藏的类型转换带来的迷惑,最好使用===或者!==操作符来比较:

5、避免使用eval()
  如果在你的代码中使用eval(),那么要记住”eval() is evil”。这个方法会将传入的字符串当做js代码来执行。如果代码是在运行前就确定的,那么没有必要使用eval()。如果代码是在运行时动态确定的,那么也有其他更安全的办法。例如使用方括号形式访问元素的属性:
// antipattern
var property = "name";
alert(eval("obj." + property));

// preferred
var property = "name";
alert(obj[property]);
  使用eval()还有安全问题,比如运行网络上的一段代码,而这段代码又被别人篡改了。在处理Ajax请求返回的JSON数据的时候,最好还是使用浏览器内建的处理方法,如果对于低端的浏览器不支持的,可以从JSON.org上下载对应的处理库。

6、使用parseInt()转换处理数字
  使用parseInt()你可以将字符串转为数字。这个方法支持第二个表示进制的参数,常常被忽略。问题常常在处理一段以0开始的字符串的时候。在ECMAS3标准中,以0开始表示八进制,但是在ES5中又改了,所以为了避免麻烦,最好还是标明第二个参数。

7、编码规范
  编码的时候遵循一定的规范,可以让代码增强可移植性,并且更加便于阅读和理解。加入团队的新人,在阅读了代码规范之后,可以更加快速的溶入团队,并理解其他人员开发的代码。

8、缩进
  代码如果没有缩进,那基本上没法阅读了。比这更糟的是不规范的缩进,看着好像缩进了,但是乱七八糟摸不着头脑。所以缩进的使用必须规范。团队遵循统一的规范

9、大括号
  应该使用大括号,尤其在那些可用可不用的地方,如果你的if语句或者for循环只有一句话,那么大括号不是必须的,但是这种时候最好用大括号。这可以让代码保持一致,并且便于升级。

10、命名规范
  可以提高代码移植性和可维护性的一个方面是命名规范。也就是说,在取变量名的时候总是采取一贯的做法。

11、写注释
  必须给代码写注释,就算它看起来不会被别人接手。有时候,研究完一个问题,然后你看着代码觉得那是显而易见的,但是过一两周之后回头再看,你也会摸不着头脑的。

如何编写高质量的Javascript代码

1、避免全局变量,因为全局变量容易发生名称上的冲突,可维护性不好。
a,使用命名空间
b,使用闭包
c,在函数内部使用var声明

2、编写可维护的代码
a.可读性
b.连续性
c.预见性
d.看起来是一个人写的
e.有文档

3、不要扩展内建的原型
  扩展原型的构造函数,可以提供一些很强大的功能,但是有时候他太强大了。
  有时候你会去扩展Object(),Array(),Fucntion()的原型方法,这样会导致可维护性的问题,因为这会让你的代码的移植性变差。其他的开发人员使用你的代码的时候,可能只需要原生的方法,并不需要额外的功能。
  另外,你添加进去的方法,如果在循环的时候没有使用hasOwnProperty方法就会被遍历出来,这会让人很迷惑。
  所以,最好还是不要扩展基本的对象。除非是下面的情况:
a.你确定在将来根据ECMAScript规范,浏览器会添加相应的原型方法,那么是可以的,你只不过是提前实现了这个功能。
b.你确定的你要实现的方法不存在–或许有时候在代码的其他的地方实现了,或者有的浏览器支持,这都是不行的。
c.有非常清晰的文档,并且与团队成员沟通过

4、避免隐藏的类型转换
  Javascript在你比较两个变量的时候会进行类型的转换,这就是为什么 false == 0或者”" == 0会返回true。
  为了避免这种隐藏的类型转换带来的迷惑,最好使用===或者!==操作符来比较:

5、避免使用eval()
  如果在你的代码中使用eval(),那么要记住”eval() is evil”。这个方法会将传入的字符串当做js代码来执行。如果代码是在运行前就确定的,那么没有必要使用eval()。如果代码是在运行时动态确定的,那么也有其他更安全的办法。例如使用方括号形式访问元素的属性:
// antipattern
var property = "name";
alert(eval("obj." + property));

// preferred
var property = "name";
alert(obj[property]);
  使用eval()还有安全问题,比如运行网络上的一段代码,而这段代码又被别人篡改了。在处理Ajax请求返回的JSON数据的时候,最好还是使用浏览器内建的处理方法,如果对于低端的浏览器不支持的,可以从JSON.org上下载对应的处理库。

6、使用parseInt()转换处理数字
  使用parseInt()你可以将字符串转为数字。这个方法支持第二个表示进制的参数,常常被忽略。问题常常在处理一段以0开始的字符串的时候。在ECMAS3标准中,以0开始表示八进制,但是在ES5中又改了,所以为了避免麻烦,最好还是标明第二个参数。

7、编码规范
  编码的时候遵循一定的规范,可以让代码增强可移植性,并且更加便于阅读和理解。加入团队的新人,在阅读了代码规范之后,可以更加快速的溶入团队,并理解其他人员开发的代码。

8、缩进
  代码如果没有缩进,那基本上没法阅读了。比这更糟的是不规范的缩进,看着好像缩进了,但是乱七八糟摸不着头脑。所以缩进的使用必须规范。团队遵循统一的规范

9、大括号
  应该使用大括号,尤其在那些可用可不用的地方,如果你的if语句或者for循环只有一句话,那么大括号不是必须的,但是这种时候最好用大括号。这可以让代码保持一致,并且便于升级。

10、命名规范
  可以提高代码移植性和可维护性的一个方面是命名规范。也就是说,在取变量名的时候总是采取一贯的做法。

11、写注释
  必须给代码写注释,就算它看起来不会被别人接手。有时候,研究完一个问题,然后你看着代码觉得那是显而易见的,但是过一两周之后回头再看,你也会摸不着头脑的。

JavaScript 代码的关键原则是什么?

答案:

JavaScript代码的关键原则有以下几点:

1. 可读性:编写易于阅读和理解的代码,使用有意义的变量名、函数名和注释。

2. 简洁性:避免冗余代码,将复杂的问题分解成简单的部分。

3. 模块化:将代码分解成的、可重用的模块,以便于维护和扩展。

4. 遵循语法规则:遵循JavaScript的语法规则,确保代码的正确性和一致性。

5. 异步编程:使用异步编程模式,如回调函数、Promises或async/await,以提高程序的性能和响应能力。

6. 错误处理:正确处理可能出现的错误和异常情况,使用try/catch语句来捕获和处理错误。

7. 性能优化:优化代码以提高执行速度,减少内存占用和CPU使用率。

8. 测试:编写测试用例,确保代码的正确性和稳定性。

JavaScript编程开发技巧?

随着互联网的不断发展,关于JavaScript编程开发语言的使用也被广大程序员掌握。而今天我们就一起来了解一下,JavaScript编程开发的一些技巧都有哪些。

JSON.stringify

我们平时经常会用到JSON对象,比如当我们要实现对象的深拷贝时,我们可以用JSON对象的JSON.stringify和JSON.parse来拷贝一个完全一样的对象,而不会对原对象产生任何引用关系。在使用localStorage时,也会用到它,因为localStorage只能存储字符串格式的内容,所以,我们在存之前,将数值转换成JSON字符串,取出来用的时候,再转成对象或数组。

参数:

value:将要被序列化的变量的值

replacer:替代器。可以是函数或者是数组,如果是一个函数,则value每个属性都要经过这个函数的处理,该函数的返回值就是后被序列化后的值。如果是一个数组,则要求该数组的元素是字符串,且这些元素会被当做value的键(key)进行匹配,后序列化的结果,是只包含该数组每个元素为key的值。

space:指定输出数值的代码缩进,美化格式之用,可以是数字或者字符串。如果是数字(大为10)的话,代表每行代码的缩进是多少个空格。如果是字符串的话,该字符串(多前十个字符)将作显示在每行代码之前。

用Set来实现数组去重

在ES6中,引入了一个新的数据结构类型:Set。而Set与Array的结构是很类似的,且Set和Array可以相互进行转换。

数组去重,也算是一个比较常见的前端面试题了,方法有很多种,这里不多赘述。下面我们看看用Set和...(拓展运算符)可以很简单的进行数组去重。

用块级作用域避免命名冲突

在开发的过程中,通常会遇到命名冲突的问题,就是需要根据场景不同来定义不同的值来赋值给同一个变量。下面昌平IT培训介绍一个使用ES6中的块级作用域来解决这个问题的方法。

函数参数值校验

我们知道,在ES6中,为函数增加了参数默认值的特性,可以为参数设定一些默认值,可以让代码更简洁,可维护。

六三科技网还为您提供以下相关内容希望对您有帮助:

如何改进javascript代码的性能_javascript技巧

O(n*n) :平方,总执行时间和数量有关,每个值至少获取N次,如:插入排序ok,有了上面的知识,我们就可以对javascript进行一些算法上的优化了。看代码:这段代码进行了4次常量值的查找:数字5,变量value,数字10,变量sum,这段代码的算法复杂...

如何编写高质量JS代码(续)_javascript技巧

2.2 熟练掌握高阶函数高阶函数无非是那些将函数作为参数或返回值的函数,将函数作为参数(通常称为回调函数,因为高阶函数"随后调用"它)是一种特别强大、富有表现力的惯用法,也在js程序中被大量使用。考虑数组的标准sort方法,为了对所有数...

JavaScript编程开发技巧?

space:指定输出数值的代码缩进,美化格式之用,可以是数字或者字符串。如果是数字(大为10)的话,代表每行代码的缩进是多少个空格。如果是字符串的话,该字符串(多前十个字符)将作显示在每行代码之前。用Set来实现数组去重...

如何提升JavaScriptWeb性能的技巧总结

如果你想更深入地了解循环的性能,Zakas提供了一种高级的循环优化技巧,使用异步进行循环(碉堡了!)8. 为HTML集合对象定义数组JavaScript使用了大量的HTML集合对象,比如 document.forms,document.images 等等。通常他们被诸如 getElementsByTagNam...

如何编写高质量的Javascript代码

1、避免全局变量,因为全局变量容易发生名称上的冲突,可维护性不好。a,使用命名空间 b,使用闭包 c,在函数内部使用var声明 2、编写可维护的代码 a.可读性 b.连续性 c.预见性 d.看起来是一个人写的 e.有文档 3、...

Web前端新手应该知道的JavaScript开发技巧有哪些?

1、尽可能的保持代码简洁可能大家都听到过了N遍这个代码简洁问题了。作为一个开发人员你可能在你的代码开发过程中使用了很多次,但千万不要在js开发中忘记这点。§尽量在开发模式中添加注释和空格,这样保持代码的可读性§在...

Web前端工程师应该知道的提高JavaScript技能的技巧!

技能的技巧,下面让我们一起来看一看吧!01、变量赋值(值vs引用)理解JavaScript如何给变量赋值可以帮助我们减少一些不必要的bug。如果你不理解这一点,可能很容易地编写被无意中更改值的代码。JavaScript总是按照值来给变量赋值。这一部分...

javascript如何进行流程控制(附代码)

= 0 ) { document.write("不能被整除"); }多个if编写起来代码复杂度很大,所以提供另外一种双选择的语法: if(条件) { }else { }如果if条件为真,则执行第一个大括号内容,否则执行else后面大括号内容。在实际开发...

javascript:;怎么解决?

这样可以防止页面自动滚动回顶部,并确保JavaScript代码不会执行;2、将JavaScript代码移动到外部文件中:可以将JavaScript代码移动到一个单独的外部文件中,并使用链接或按钮的“src”属性来引用该文件。这样可以避免使用“javascrip...

JavaScript多并发问题如何处理_javascript技巧

每完成一个异步函数加1,或者设置一个数组,每执行完一个异步函数更新数组。回调计数循环阻塞循环非阻塞不建议过多使用,以免影响性能第三方框架实现jquery目前我在项目中采用的方式

本文如未解决您的问题请添加抖音号:51dongshi(抖音搜索懂视),直接咨询即可。

Top