JavaScript 性能优化2 学习笔记

文章内容输出来源:拉勾大前端高薪训练营

1、性能测试工具 JSBench 使用

网址:https://jsbench.me/ 常用的 JSperf 已经停止维护了

  • Setup HTML 想初始化的dom
  • Setup JS 前置统一的js代码
  • Test Case 添加测试用例,具体的测试代码(一般两个)
  • Teardown JS 后置统一的js代码
    (每秒的次数 越大越好)

性能测试细节:尽可能开一个标签页、当前的进程不要关掉、多次执行

2、堆栈中代码执行流程

  • 首先堆内存中创建执行环境栈,执行环境栈中存放不同的执行上下文
  • 代码从上往下之下,先创建全局上下文,
  • 基本数据类型值存在栈内存中,由JS主线程管理,
    引用类型存放在堆内存中,一般由GC回收处理
  • 每当遇到函数执行,重新生成执行上下文进栈,
    代码执行完,由是否产生闭包决定我们当前的上下文中引用的堆要不要被释放掉
let a = 10;
function foo(b){
    let a = 2;
    function baz(c){
        console.log(a+b+c);
    }
    return baz;
}
let fn = foo(2);
fn(3);
ECStack 执行环境栈:
    EC(baz执行上下文)
        this = window
        <baz.ao, foo.ao, vo>
        AO:
            arguments:{0: 3}
            c = 3
            console.log(a + b + c)
            3 + 2 + 1 = 7
    EC(foo执行上下文)  
        this = window  
        <foo.ao, vo> // foo.ao代表自己的作用域
        AO: 
            arguments:{0: 2}
            a = 2
            baz = AB2 [[scope]] foo.AO
    
    EC(全局执行上下文)
        VO: 
            a = 10 (字面量直接存在栈中)
            foo = AB1 [[scope]] VO
            fn = AB2
堆内存:  AB1
    function foo(b){...}
    name: foo
    length: 1

堆内存:  AB2
    function baz(c){...}
    name: baz
    length: 1

3、减少判断层级

function doSomething(part, chapter){
    const parts = ['ES2016', '工程化', 'Vue', 'React', 'Node'];
    if(part){
        if(parts.includes(part)){
            console.log('属于当前课程')
            if(chapter > 5){
                console.log('您需要提供VIP身份')
            }
        }
    }else{
        console.log('请确定模块信息')
    }
}
doSomething('ES2016', 6);

//优化后
function doSomething(part, chapter){
    const parts = ['ES2016', '工程化', 'Vue', 'React', 'Node'];
    if(!part){
        console.log('请确定模块信息');
        return
    }
    if(!parts.includes(part)) return
    console.log('属于当前课程')
    if(chapter > 5){
        console.log('您需要提供VIP身份')
    }
}

4、减少作用域链查找层级

避免全局查找
全局查找相关

  • 目标变量不存在于当前作用内,通过作用域链向上查找
  • 减少全局查找降低实践消耗
  • 减少不必要的全局变量定义
  • 全局变量数据局部化
var name = 'zce';
function foo(){
    //name = 'zce666'; //这里的name 是属于全局的
    
    //优化
    var name = 'zce666';
    function baz(){
        var age = 18;
        console.log(age);
        console.log(name)
    }
    baz();
}
foo();
//快建立在内存空间消耗上

5、减少数据读取次数

//html
<div id="skip" class="skip"></div>

var oBox = document.getElementById('skip');
function hasEle(ele, cls){
    return ele.className == cls;
}
console.log(hasEle(oBox, 'skip'));

//优化
function hasEle(ele, cls){
    var className = ele.className 
    return className == cls;
}
//快建立在内存空间消耗上

6、字面量与构造式

用字面量比构造式执行效率高

var test = () => {
    let obj = new Object();
    obj.name = 'sz';
    obg.age = 18;
    return obj;
}
console.log(test());

//字面量
var test = () => {
    let obj = {
        name: 'sz',
        age: 18
    }
    return obj;
}
console.log(test());

//示例二
var str1 = '你好呀'; //字符串
var str2 = new String('你好呀'); //对象
console.log(str1);
console.log(str2);

7、减少循环体中活动

避免循环引用

  • 全局引用指多个对象间存在互相引用
  • 采用字面量替换New操作
  • setTimeout 替换 setInterval
  • 采用事件委托
  • 合并循环变量和条件
var test = () => {
  var i
  var arr = ['zce', 18, '你好呀'];
  for(i = 0; i < arr.length; i++){
    console.log(arr[i])
  }
}
test();

//优化后
var test = () => {
  var i
  var arr = ['zce', 18, '你好呀'];
  var len = arr.length;
  for(i = 0; i < len; i++){
    console.log(arr[i])
  }
}
//再优化
var test = () => {
  var arr = ['zce', 18, '你好呀'];
  var len = arr.length;
  while(len--){
    console.log(arr[len]);
  }
}

8、减少声明及语句数

//html
<div id="box" style="width: 100px; height: 100px;"></div>

var oBox = document.getElementById('box');
var test = (ele) => {
    let w = ele.offsetWidth;
    let h = ele.offsetHeight
    return w * h;
}
//优化后
var test = (ele) => {
    return ele.offsetWidth * ele.offsetHeight;
}
console.log(test(oBox));

//示例2
var test = () => {
    var name = 'zc';
    var age = 18;
    return name + age;
}

var test = () => {
    var name = 'sc',
        age = 18;
    return name + age;
}
console.log(test())

9、采用事件委托

子元素的事件 委托给 父元素来完成

//html
<ul id="ul">
    <li>ZC</li>
    <li>18</li>
</ul>
  
var list = document.querySelectorAll('li');
function showTxt(ev){
    console.log(ev.target.innerHTML);
}
for(let item of list){
    item.onclick = showTxt;
}

//优化
var oUl = document.getElementById('ul');
oUl.addEventListener('click', showTxt, true);
function showTxt(ev){
    var obj = ev.target;
    if(obj.nodeName.toLowerCase() === 'li'){
      console.log(obj.innerHTML);
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容