前言

第二章主要讲解各种变量作用域,通过这章的学习,接触到了很多之前没有接触过的东西,比如不经常用到的eval,命名函数表达式,with语句块等,下面是一个列表,我对各节的一点点个人总结,很多都是自己的收获和认识。可能有很多认识的误区,毕竟水平有限。如果有那里认识不对的地方,还希望可以在评论中指出来,这样可以得到大家在学习的帮助,也是很不错的。

第8条:尽量少用全局对象

个人总结:

解释全局对象在JS中定义的随意性,导致所有人都可以去定义去修改,导致命名冲突。对这样的全局对象进行依赖,导致不可知的运行结果,极不利于后期的维护,以及对代码重用造成的影响。提供了几点建议,包括利于JS代码的函数产生的作用域来对变量进行划分。另外,对宿主环境的全局对象,尽量少做修改。以免对其它引用库造成影响。在对运行环境进行适配时,对全局对象进行特性检测,尽量使用环境提供的原生对象。因为平台环境中的对象的正确性和一致性,及性能都有优势。

提示

  • 避免声明全局变量

  • 尽量声明局部变量

  • 避免对全局对象添加属性

  • 使用全局对象来做平台检测

第9条:始终声明局部变量

个人总结:

这一节感觉就是上一节的补充,当你尽量少用全局对象时,那你用什么呢?就是始终声明局部变量。主要是在写代码时候不要忘记,var,如果没有这个就自动变成全局的啦。对于对自己代码书写能力不是很自信的人来说,可以用一些构建工具,里面加点代码检测功能插件。然后每次跑一下就知道代码里有没有对应的错误了,这里推荐使用gulp。可以到之前的一个文章里查看使用方法

提示

  • 始终使用var声明新的局部变量

  • 考虑使用lint工具帮助检查未绑定的变量

第10条:避免使用with

个人总结:

使用with,可以节约书写一些对象的名称,在代码里可以少打点代码。我没用过with,以前只知道它会改变this的指向。从学习这节里认识到,它的使用,可能会影响你代码里对应的变量的值的查找,而且每个变量都会在with对象的原型链中查找是否存在,从而造成性能的降低。在后期代码的维护过程中,也可能破坏原来使用with引用对象的函数或方法,因为有可能后期为with的对象添加了新的属性或方法和它们中的变量重名,造成功能无法正常完成,破坏函数的预期功能。做为替代方法,可以使用一些短命名,如我经常会用的var win=window,doc=document;之类的,在有对同一对象大量方法或属性使用时可以用这个方法来减少代码量。

提示

  • 避免使用with语句

  • 使用简短的变量名代替重复访问的对象

  • 显式地绑定局部变量到对象属性上,而不要使用with语句隐式地绑定它们。

第11条:熟练掌握闭包

个人总结:

这就是一个名词,知道什么时候会出现这种情况就行了。主要也就是两个,一个是函数可以产生作用域,二个是定义在里面的函数可以访问它外层函数的变量对象(哪怕外面的函数都已经返回了)。这个会占用内存,因为一直要保存外层函数的变量对象,如果想释放掉闭包,显示地设置为null就OK了。闭包用得较多的地方,一个是定义和调用的时间点不统一,比如:绑定事件句柄的函数的定义,定义的时间点,和调用的时间点不定(事件触发的时候),二个是就是在面试的时候,各种,变量值的求值是什么。

提示

  • 函数可以引用定义在其外部作用域的变量

  • 闭包比创建它们的函数有更长的生命周期

  • 闭包在内部存储其外部变量的引用,并能读写这些变量

第12条:理解变量声明提升

个人总结:

变量提升,看到较多的地方,也是各种面试题。理解变量提升后,可以把考试的题目先按照JS解析的过程,把一些var,function声明都写前头去,再结合作用域访问顺序,基本都能答对。这里主要就是JS没有块级作用域,作用域的最小单位就是函数。变量声明提升就是找最近的function就好了,然后把各种声明都放到这里。

提示

  • 在代码块中的变量声明会被隐式提升到封闭函数的顶部

  • 重声明变量被视为单个变量

  • 考虑手动提升局部变量声明,从而避免混淆

第13条:使用立即调用的函数表达式创建局部作用域

个人总结:

只要看过一些库的源码的,都应该都这个不陌生。(function(){})();这就是创建完成后就执行了,当然这里要以传入一些参数。这里面创建的变量名,只要用var,一定是局部的,这里返回出来的函数一定都是闭包,可以对此函数的内部变量进行访问。可以解决上面提到的事件绑定对外部变量的引用问题。至于书上说的,不能使用break,continue。以及对this,arguments变量的影响。对this,arguments变量的影响。this要不就指向新对象,要不就指向window。函数作为构造函数时,并使用new关键词调用时,或函数作为对象的方法时,this指向对象。直接运行的函数this指向window对象。立即运行函数是直接执行的,所以this指向window。(个人理解可能有错,请指出)。arguments就是函数参数对象,立即执行函数也是函数也有参数对象。注意这点就应该没问题了。

提示

  • 理解绑定与赋值的区别

  • 闭包通过引用而不是值复制它们的外部变量

  • 使用立即调用的函数表达式来创建局部作用域

  • 当心在立即调用的函数表达式中包裹代码块可能改变其行为的情形

第14条:当心命名函数表达式笨拙的作用域

个人总结:

命名函数表达式,在一些递归的情况下使用过,比如写一个动画函数,里面的迭代函数就是使用这个。但一般我是直接在给立即执行函数表达式一个名字。
形如

(function a(){
//....
a();
})();

它的作用域也只能在内部访问,书上说的各种环境下的解析什么的,也没遇到过。现在使用环境:浏览器,nodejs,暂时没发现什么问题。在这里只是觉得把命名函数表达式的作用域表示为对象挺有意思,但在浏览器里试了一下,没有问题,可能是都实现了ES5的原因吧。
改进栈跟踪这个真心没用过,如试一下看看。

提示

  • 在Error对象和高度器中使用命名函数表达式改进栈跟踪

  • 在ES3和有问题的JS环境中谨记函数表达式作用域会被Object.prototype污染

  • 谨记在错误百出的JS环境中会提升命名函数表达式声明,并导致命名函数表达式的重复存储

  • 考虑避免使用命名函数表达式或在发布前删除函数名

  • 如果你将代码发布到正确实现的ES5环境中,那么就不会出现问题了

第15条:当心局部块函数声明笨拙的作用域

个人总结:

嵌套函数声明,立即执行函数里定义的函数就是嵌套的。因为没有块级作用域,所以在块里声明函数,会自动提升函数声明到作用域的顶部。如果要根据条件来声明一个函数,可以用函数表达式的形式对变量进行赋值,从而得到相应功能的函数。比如:事件注册的函数

function addEvent(o,e,f){
var addE;
if(document.addEventListener){
addE=function(o,e,f){
o.addEventListener(e,f,false);
}
}else if(document.attachEvent){
addE=function(o,e,f){
o.attachEvent('on'+e,f);
}
}else{
addE=function(o,e,f){
o['on'+e]=f;
}
} addE(o,e,f);
addEvent=addE;
}

提示

  • 始终将函数声明置于程序或被包含的函数的最外层以避免不可移植的行为

  • 使用var声明和有条件的赋值语句替代有条件的函数声明

第16条:避免使用eval创建局部变量

个人总结:

在工作中用得真心不多,只在json数据的处理,也就是把字符串转化为json对象这个过程中使用过。还有就是通过这节文章,了解到对外部作用域的影响是不可预知的,因为你不知道将要处理的字符串中,是否包括对作用域中变量的修改(包括全局变量的修改)。建议使用立即执行函数对处理代码进行隔离。

提示

  • 避免使用eval函数创建的变量污染调用者的作用域

  • 如果eval函数代码可能创建全局变量,将此调用封装到嵌套的函数中以防止作用域的污染

第17条:间接调用eval函数优于直接调用

个人总结:

大多数函数只能访问定义它们所在的作用域,而不能访问除此之外的作用域。eval函数可以访问调用它时的整个作用域的能力,也就是那里调用,它就可以访问那里的作用域。功能很强大,但导致没法优化JS。因为每个调用了eval的函数都要确保在运行时整个作用域对eval函数可访问。可以使用(0,eval)(src)变成间接调用来提高性能。其它的我觉得都不用知道,毕竟这个本来用得就少,至少我用得少。

提示

  • 将eval函数同一个毫无意义的字面量包裹在序列表达式中以达到强制使用间接调用eval函数的目的

  • 尽可能间接调用eval函数,而不要直接调用eval函数

[Effective JavaScript 笔记]第2章:变量作用域--个人总结的更多相关文章

  1. [Effective JavaScript 笔记]第3章:使用函数--个人总结

    前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...

  2. [Effective JavaScript 笔记]第4章:对象和原型--个人总结

    前言 对象是js中的基本数据结构.对象在js语言编码中也随处可见,比如经常会用到的函数,也是一个Function构造函数,Function.prototype原型对象.每当声明一个函数时,都会继承Fu ...

  3. [Effective JavaScript 笔记]第5章:数组和字典--个人总结

    前言 这节里其实一直都在讨论对象这个在js中的万能的数据结构.对象可以表式为多种的形式,表示为字典和数组之间的区别.更多的我觉得这章讨论多的是一些对应实现功能的相关操作,有可能出现的bug以及如何避免 ...

  4. [Effective JavaScript 笔记]第6章:库和API设计--个人总结

    前言 又到了一章的总结,这章里的内容.是把我从一个代码的使用者,如何换位成一个代码的编写者.如何让别人用自己的代码更容易,不用去注意太多的无用细节,不用记住冗长的函数名.在使用API时怎样避免使用者会 ...

  5. [Effective JavaScript 笔记]第7章:并发--个人总结

    前言 这一章的内容学到了事件队列和异步的API.js只是运行在其他应用程序的脚本语言.js即依赖于应用程序,也独立与应用程序.可以使它可以在多平台,多种环境上运行.ECMAScript标准中没有关于并 ...

  6. [Effective JavaScript 笔记] 第1章:让自己习惯javascript小结

    在这里整理一下,每条对应的提示 第1条:了解使用的js版本 确定应用程序支持的js的版本(浏览器也是应用程序噢) 确保使用的js特性是应用程序支持的(要不写了也运行不了) 总是在严格模式下编写和测试代 ...

  7. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  8. [Effective JavaScript 笔记]全书总结

    这本书中就像它前言中说的那样,这本书不是给初学者的.需要一定的基础,而且有一定的编码实践,才能很好的理解书里讲到的内容.学习一门编程语言,需要熟悉它的语法.形式和结构,这样才会编写合法的.符合语义的. ...

  9. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

随机推荐

  1. php模式设计之 观察者模式

    这是我写的<php模式设计>的第五篇.前面的四篇在不断学习不断加深认识,到了今天再看观察者模式,觉得非常容易理解.这也许就是我们积少成多的结果吧.希望还是能够不断进步. 开篇还是从名字说起 ...

  2. [C语言]一个很实用的服务端和客户端进行TCP通信的实例

    本文给出一个很实用的服务端和客户端进行TCP通信的小例子.具体实现上非常简单,只是平时编写类似程序,具体步骤经常忘记,还要总是查,暂且将其记下来,方便以后参考. (1)客户端程序,编写一个文件clie ...

  3. Bootstrap系列 -- 29. 按钮组

    单个按钮在Web页面中的运用有时候并不能满足我们的业务需求,常常会看到将多个按钮组合在一起使用,比如富文本编辑器里的一组小图标按钮等 按钮组和下拉菜单组件一样,需要依赖于button.js插件才能正常 ...

  4. 20步打造最安全的NGINX WEB服务器

    Nginx 是一个轻量级的,高性能的Web服务器以及反向代理和邮箱(IMAP/POP3)代理服务器.它运行在UNIX,GNU /linux,BSD 各种版本,Mac OS X,Solaris和Wind ...

  5. 调研Android平台开发环境的发展演变

    Android是Google推出的开源手机操作系统,主要以开发应用为主,要进行Android开发首先得搭建好开发平台.最近在搭建Android的开发环境,发现往往一个小问题都能花费你大半天时间,从刚开 ...

  6. 百分比定位加position定位的常用布局

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  7. Java基础-四要素之一《封装》

    封装从字面上来理解就是包装的意思,专业点就是信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保 ...

  8. BIEEE 创建多维钻取分析(4)

    在上一节时,我们创建了一个基于部门号的工资分类汇总. 这里就引出了一个概念:维度 专业的解释大家自行百度,这里就不班门弄斧了.从数据的使用角度看,维度可以简单的理解成“数据分类汇总的一种依据”. 按“ ...

  9. RequestMethod.DELETE相关,如何用jquery实现RequestMethod.DELETE请求

    Spring MVC添加支持Http的delete.put请求!(HiddenHttpMethodFilter) Spring3.0之后->Spring MVC过滤器-HiddenHttpMet ...

  10. 【ASP.NET Web API教程】6.1 媒体格式化器

    http://www.cnblogs.com/r01cn/archive/2013/05/17/3083400.html 6.1 Media Formatters6.1 媒体格式化器 本文引自:htt ...