栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > Web开发 > Html/CSS

前端性能优化补充篇

Html/CSS 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

前端性能优化补充篇

前言

看了一下之前发布的文章,关于前端性能优化的,有网站前端性能优化之javascript和css及jquery的 jquery编程的标准写法和最佳实践 。前端性能优化是一个不断追求的过程,前面的文章虽然讲解了一些性能优化,但是关于性能优化的路还有很长,很多东西都没有提及。今天,我在前面的基础之上,再来简单总结一些常用的性能优化方式。

运算符

1、使用运算符时,尽量使用+=,-=、*=、=等运算符号,而不是直接进行赋值运算。

2、位运算。

当进行数学运算时位运算较快,位运算操作要比任何布尔运算或算数运算快,如取模,逻辑与和逻辑或也可以考虑用位运算来替换。

有同学问,常见的js位运算符有哪些?常见的位运算符有“~,&,|,^,.<<,>>,>>>”等等。

关于位运算的应用,我前面也有文章提及,js运算符单竖杠“|”的用法和作用是什么?以及javascript实用技巧,js小知识大家可以去看看。

常规优化
1、switch语句。

若有一系列复杂的if-else语句,可以转换成单个switch语句则可以得到更快的代码,还可以通过将case语句按照最可能的到最不可能的顺序进行组织,来进一步优化。

例如:

function getCategory(age) {
    var category = "";
    switch (true) {
 case isNaN(age):
     category = "not an age";
     break;
 case (age >= 50):
     category = "Old";
     break;
 case (age <= 20):
     category = "Baby";
     break;
 default:
     category = "Young";
     break;
    };
    return category;
}
getCategory(5);  //Baby

这样的稍微复杂一些的,我们尽量就不用if/else了,当然,简单的判断,还是推荐if/else。

2、减少页面的重绘

我的jquery文章优化中,提及了这一项。

代码如下:

var str = "这是一个测试字符串";

var obj = document.getElementsByTagName("body");
for(var i = 0; i < 100; i++){
    obj.innerHTML += str + i;
}

var obj = document.getElementsByTagName("body");
var arr = [];
for(var i = 0; i < 100; i++){
    arr[i] = str + i;
}
obj.innerHTML = arr.join("");

3、传递方法取代方法字符串

一些方法例如setTimeout()、setInterval(),接受字符串或者方法实例作为参数。直接传递方法对象作为参数来避免对字符串的二次解析。

传递方法

setTimeout(test, 1);//good
传递方法字符串

setTimeout('test()', 1);//不能说bad,只能说not good

4、使用原始操作代替方法调用

方法调用一般封装了原始操作,在性能要求高的逻辑中,可以使用原始操作代替方法调用来提高性能。

原始操作

var min = a方法实例
var min = Math.min(a, b);//not good

5、定时器

如果针对的是不断运行的代码,不应该使用setTimeout,而应该是用setInterval。setTimeout每次要重新设置一个定时器。

6、最小化语句数

例如:

多个变量声明

var i = 1;
var j = "hello";
var arr = [1,2,3];
var now = new Date();

var i = 1,
    j = "hello",
    arr = [1,2,3],
    now = new Date();

插入迭代值

var name = values[i];
i++;

var name = values[i++];

使用数组和对象字面量,避免使用构造函数Array(),Object()

var a = new Array();
a[0] = 1;
a[1] = "hello";
a[2] = 45;
var o = new Obejct();
o.name = "bill";
o.age = 13;

var a = [1, "hello", 45];
var o = {
    name : "bill",
    age : 13
};

类型转换

1、把数字转换成字符串。

应用""+1,效率是最高。

性能上来说:""+字符串>String()>.toString()>new String()。

String()属于内部函数,所以速度很快。
.toString()要查询原型中的函数,所以速度略慢。
new String()最慢。

2、浮点数转换成整型。

错误使用使用parseInt()。

parseInt()是用于将字符串转换成数字,而不是浮点数和整型之间的转换。

应该使用Math.floor()或者Math.round()。

Math是内部对象,所以Math.floor()其实并没有多少查询方法和调用的时间,速度是最快的。

循环
1、定义变量,避免每次获取

   
var divs = document.getElementsByTagName("div");    
for(var i = 0; i < divs.length; i++){   
    ...  
}    
  
var divs = document.getElementsByTagName("div");   
for(var i = 0, len = divs.length; i < len; i++){   
    ... 
}

2、避免在循环中使用try-catch。

try-catch-finally语句在catch语句被执行的过程中会动态构造变量插入到当前域中,对性能有一定影响。

如果需要异常处理机制,可以将其放在循环外层使用。

循环外使用try-catch

try {
  for ( var i = 0; i < 200; i++) {}
} catch (e){}

3、避免遍历大量元素,尽量缩小遍历范围。

作用域链和闭包优化
1、作用域。

作用域(scope)是JAVAscript编程中一个重要的运行机制,在JAVAscript同步和异步编程以及JAVAscript内存管理中起着至关重要的作用。 在JAVAscript中,能形成作用域的有如下几点。

函数的调用
with语句
with会创建自已的作用域,因此会增加其中执行代码的作用域的长度。
全局作用域。

以下代码为例:

var foo = function() {
  var local = {};
};
foo();
console.log(local); //=> undefined

var bar = function() {
  local = {};
};
bar();
console.log(local); //=> {}



local = {};
// 这里的定义等效于
global.local = {};

2、作用域链

在JAVAscript编程中,会遇到多层函数嵌套的场景,这就是典型的作用域链的表示。

function foo() {
  var val = 'hello';
  function bar() {
    function baz() {
      global.val = 'world;'
    };
    baz();
    console.log(val); //=> hello
  };
  bar();
};
foo();

3、减少作用域链上的查找次数

for(var i = 0; i < 10000; i++){
    var but1 = document.getElementById("but1");
}


var doc = document;
for(var i = 0; i < 10000; i++){
    var but1 = doc.getElementById("but1");
}

4、闭包

JAVAscript中的标识符查找遵循从内到外的原则。

function foo() {
  var local = 'Hello';
  return function() {
    return local;
  };
}
var bar = foo();
console.log(bar()); //=> Hello

闭包是JAVAscript的高级特性,因为把带有​​内部变量引用的函数带出了函数外部,所以该作用域内的变量在函数执行完毕后的并不一定会被销毁,直到内部变量的引用被全部解除。所以闭包的应用很容易造成内存无法释放的情况。

良好的闭包管理。

循环事件绑定、私有属性、含参回调等一定要使用闭包时,并谨慎对待其中的细节。

循环绑定事件,我们假设一个场景:有六个按钮,分别对应六种事件,当用户点击按钮时,在指定的地方输出相应的事件。

var btns = document.querySelectorAll('.btn'); // 6 elements
var output = document.querySelector('#output');
var events = [1, 2, 3, 4, 5, 6];
// Case 1
for (var i = 0; i < btns.length; i++) {
  btns[i].onclick = function(evt) {
    output.innerText += 'Clicked ' + events[i];
  };
}

// Case 2
for (var i = 0; i < btns.length; i++) {
  btns[i].onclick = (function(index) {
    return function(evt) {
      output.innerText += 'Clicked ' + events[index];
    };
  })(i);
}

// Case 3
for (var i = 0; i < btns.length; i++) {
  btns[i].onclick = (function(event) {
    return function(evt) {
      output.innerText += 'Clicked ' + event;
    };
  })(events[i]);
}

避开闭包陷阱

闭包是个强大的工具,但同时也是性能问题的主要诱因之一。不合理的使用闭包会导致内存泄漏。

闭包的性能不如使用内部方法,更不如重用外部方法。

由于IE 9浏览器的DOM节点作为COM对象来实现,COM的内存管理是通过引用计数的方式,引用计数有个难题就是循环引用,一旦DOM引用了闭包(例如event handler),闭包的上层元素又引用了这个DOM,就会造成循环引用从而导致内存泄漏。

善用函数

使用一个匿名函数在代码的最外层进行包裹。

;(function() { // 主业务代码 })();

有的甚至更高级一点:

;(function(win, doc, $, undefined) {
  // 主业务代码
})(window, document, jQuery);

甚至连如RequireJS, SeaJS, OzJS 等前端模块化加载解决方案,都是采用类似的形式:

define(['jquery'], function($) {
  // 主业务代码
});

define('m​​odule', ['dep', 'underscore'], function($, _) {
  // 主业务代码
});

善用回调函数
在制作网页过程中,用的比较多的地方,我们通常封装成函数。在封装函数的时候,善用运用回调函数。

例子如下:

function getData(callBack){
    $.ajax({
 url:"",
 data:{},
 dataType:"json",
 type:"get",
 success:function(data){
     callBack(null,data)
 }
    })

}

我们在调用的时候可以如下:

getData(function(error,data){
 console.log(data)
})

数组中插入元素最快的方法
向一个数组中插入元素是平时很常见的一件事情。你可以使用push在数组尾部插入元素,可以用unshift在数组头部插入元素,也可以用splice在数组中间插入元素。 但是这些已知的方法,并不意味着没有更加高效的方法。

尾部插入元素

我们有2个数组

var arr = [1,2,3,4,5];
var arr2 = [];

测试如下:

 arr[arr.length] = 6; // 最快
arr.push(6); // 慢34.66%
arr2 = arr.concat([6]); // 慢85.79%

前面插入元素

var arr = [1,2,3,4,5];
arr.unshift(0); 
[0].concat(arr);

发现:

[0].concat(arr); // 快
arr.unshift(0); // 慢64.70%

向数组中间添加元素

使用splice可以简单的向数组中间添加元素,这也是最高效的方法。

var items = ['one', 'two', 'three', 'four'];
items.splice(items.length / 2, 0, 'hello');

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/218570.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号