js中有四种基本的数据存取位置。分别是:字面量、本地变量、数组元素、对象成员。

字面量:只代表自身,不存储在特定位置。js的字面量有:字符串、数字、布尔值、对象、数组、函数、正则表达式、以及特殊的null和undefined。

本地变量:开发人员使用关键字var定义的数据存储单元。

数组元素:存储在js数组对象内部,以数字作为索引。

对象成员:存储在js对象内部,以字符串作为索引。

总体来说:字面量和本地变量的访问速度快于数组项和对象成员的访问速度。

管理作用域:

  • 作用域链和标示符解析

作用域链:内部属性[[scope]]包含了一个函数被创建的作用域中对象的集合。

函数的作用域链决定了哪些数据能被函数访问。函数作用域中的每个对象被称为一个可变对象,每个可变对象都以“键值对”的形式存在。当一个函数创建后,它的作用域链会被创建此函数的作用域中可访问的数据对象所填充。

例:function add(num1,num2){

var sum = num1+num2;return sum;

}

当函数add()创建时,它的作用域链中插入了一个对象变量,这个全局对象代表着所有在全局范围内定义的变量。

函数add()的作用域将会在执行时用到。假设执行:var total = add(5,10); 执行此函数时会创建一个称为执行环境的内部对象。一个执行环境定义了一个函数执行时的环境。函数执行时对应的执行函数都是独一无二的,所以多次调用同一个函数就会导致创建多个执行环境。当函数执行完毕后,执行环境就被销毁。

每个执行环境都有自己的作用域链,用于解析标示符。当执行环境被创建时,它的作用域链初始化为当前运行函数的[[scope]]属性的对象。这时会创建一个被称为“活动对象”。活动对象作为函数运行时的变量对象,包含了所有局部变量,命名参数,参数集合以及this。同时被推入作用域链的最前端。执行环境销毁后,活动对象也随之销毁。

在函数执行过程中,每遇到一个变量,都会经历一次标示符解析过程以决定从哪里获取或存储数据。而此搜索过程影响了性能。

标示符解析:

一个标示符所在的位置越深,它的读写速度也就越慢。

经验法则:如果某个跨作用域的值在函数中被引用一次以上,那么就把它存储到局部变量里。访问跨作用域的值,需要遍历作用域链往上找,会导致性能的下降,而通过局部变量存储一个跨作用域的值,使得查找次数减少,性能提升。

作用域链的改变:with语句、try-catch语句中的catch子句将临时改变作用域链,创建一个新的变量对象,并推入作用域链的首位,使得函数的所有局部变量处于第二作用域链的对象,导致访问代价提高。

动态作用域:with、try-catch的catch以及eval()被认为是动态作用域。动态作用域只存在于代码执行过程中,因此无法通过静态分析检测。某些优化的js引擎尝试通过分析代码来确定哪些变量可以在特定时候被访问。这些引擎试图避开传统作用域链的查找,取代以标示符索引的方式进行快速查找。而涉及动态作用域时,这种优化方式失效,脚本引擎切换回较慢的基于哈希表的标示符识别方式。

闭包:由于闭包的特性,将导致存在于闭包的[[scope]]属性中,活动对象无法被销毁,故引起更多的内存开销。因此在使用闭包时最需要关注的性能点:在频繁访问跨作用域的标示符时,每次访问都会带来性能损失。闭包的使用关系到内存和执行速度。

  • 对象成员

js中的对象是基于原型的。原型是其他对象的基础,它定义并实行了一个新创建的对象所必须包含的成员列表。对象有两种成员类型:实例成员和原型成员。实例成员直接存在对象的实例中,原型成员则从对象的原型继承而来。

而在调用原型成员时,搜索过程会深入原型链中直到找到原型成员。而原型成员所在原型链的位置越深,访问所需时间就越多。

嵌套成员:js每次遇到点操作符时,嵌套成员会导致js引擎搜索所有对象成员。例如:location.href比window.location.href读取速度更快。

注:大部分游览器对于点表示法操作和括号表示法操作并没有明显区别,只有Safari中,点符号始终更快。

由于所有类似的性能问题都与对象成员有关,故因尽可能避免使用它们,或者说只在必要时使用对象成员。例如:多次读取同一个对象属性时,最佳做法是将属性值保存到局部变量以此来避免多次查找带来的性能开销。特别是处理嵌套对象成员时。

注:这种优化方式并不推荐用于对象的成员方法,因为许多对象方法使用this来判断执行环境,把一个对象方法保存在局部变量会导致this绑定到window,而this值的改变会使得js引擎无法正确解析它的对象成员,进而报错。

高性能javascript(记录二)的更多相关文章

  1. 高性能JavaScript笔记二(算法和流程控制、快速响应用户界面、Ajax)

    循环 在javaScript中的四种循环中(for.for-in.while.do-while),只有for-in循环比其它几种明显要慢,另外三种速度区别不大 有一点需要注意的是,javascript ...

  2. 《高性能javascript》 领悟随笔之-------DOM编程篇(二)

    <高性能javascript> 领悟随笔之-------DOM编程篇二 序:在javaSctipt中,ECMASCRIPT规定了它的语法,BOM实现了页面与浏览器的交互,而DOM则承载着整 ...

  3. JavaScript学习记录二

    title: JavaScript学习记录二 toc: true date: 2018-09-13 10:14:53 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...

  4. 《高性能Javascript》 Summary(二)

    第四章.算法和流程控制 Algorithms And Flow Control 原因:代码整体结构是执行速度的决定因素之一.代码量少不一定运行速度快,代码量多不一定运行速度慢.性能损失与组织代码和具体 ...

  5. 高性能JavaScript(1)

    ---------------------------------------------------------------------------------------------------- ...

  6. 《高性能javascript》一书要点和延伸(上)

    前些天收到了HTML5中国送来的<高性能javascript>一书,便打算将其做为假期消遣,顺便也写篇文章记录下书中一些要点. 个人觉得本书很值得中低级别的前端朋友阅读,会有很多意想不到的 ...

  7. 高性能JavaScript 重排与重绘

    先回顾下前文高性能JavaScript DOM编程,主要提了两点优化,一是尽量减少DOM的访问,而把运算放在ECMAScript这一端,二是尽量缓存局部变量,比如length等等,最后介绍了两个新的A ...

  8. 【读书笔记】读《高性能JavaScript》

    这本<高性能JavaScript>讲述了有关JavaScript性能优化的方方面面,主要围绕以下几个方面: 1> 加载顺序 2> 数据访问(如怎样的数据类型访问最快,怎样的作用 ...

  9. 《高性能javascript》学习总结

    本文是学习<高性能javascript>(Nichols C. Zakes著)的一些总结,虽然书比较过时,里面的知识点也有很多用不上了,但是毕竟是前人一步步探索过来的,记录着javascr ...

  10. 《高性能JavaScript》--读书笔记

    第一章 加载和运行 延迟脚本 defer 该属性表明脚本在执行期间不会影响到页面的构造,脚本会先下载但被延迟到整个页面都解析完毕后再运行.只适用于外部脚本 <script src="j ...

随机推荐

  1. spring mvc文件上传

    package com.haier.controller.newuser; import com.haier.commons.entity.Response; import com.haier.com ...

  2. GridView数据绑定

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs& ...

  3. 【leetcode❤python】 168. Excel Sheet Column Title

    class Solution(object):    def convertToTitle(self, n):        """        :type n: in ...

  4. 如何在IamgeButton上面添加文字

    如何在IamgeButton上面添加文字? 首先要知道,IamgeButton是不可以直接添加文字的.所以我们需要间接制作一个Button按钮 我的代码将会展示另外一个例子,与本文中的代码相似. 本文 ...

  5. 什么是js和js的基本语法

    时间:2016年12月15日 先讲讲基础语法: 大部分是来操作表单: js动态效果和数据交互(ajax?) js也有自己的API js大部分的DOM操作都是针对input的. 案例学习,对注册页面的简 ...

  6. springboot中swaggerUI的使用

    demo地址:demo-swagger-springboot springboot中swaggerUI的使用 1.pom文件中添加swagger依赖 2.从github项目中下载swaggerUI 然 ...

  7. js去除数组重复项

    /** * js去除数组重复项 */ //方法一.使用正则法 // reg.test(str),匹配得到就返回true,匹配不到返回false var arr = ["345",& ...

  8. unity自带寻路Navmesh入门教程(三)

    继续介绍NavMesh寻路的功能,接下来阿赵打算讲一下以下两个例子,先看看完成的效果:   第一个例子对于喜欢DOTA的朋友应该很熟悉了,就是不同小队分不同路线进攻的寻路,红绿蓝三个队伍分别根据三条路 ...

  9. CSS3图片倒影技术实现及原理

    CSS3图片倒影技术实现及原理 目前为止我们已经探讨了很多CSS3中的新功能和新特征.除了上面这些,实际上还有很多CSS新属性并未包含进CSS3官方标准中,像谷歌浏览器或火狐浏览器等都会利用CSS的浏 ...

  10. 20145218 GDB调试汇编堆栈过程分析

    GDB调试汇编堆栈过程分析 虚拟机中分析过程 输入gcc - g example.c -o example -m32指令在64位机器上产生32位汇编,但出现以下错误: 这时需要使用sudo apt-g ...