作家
登录

JavaScript.The.Good.Parts阅读笔记(二)作用域&闭包&减缓全局空间污染

作者: 来源:www.28hudong.com 2013-03-30 01:11:33 阅读 我要评论

如代码块 复制代码 代码如下: if (true) { int i = 100; } print(i); //错误,变量i没有声明 如上面例子所示,代码块外的函数是无法访问i变量的。 但在javaScript里,情况则完全不同。 复制代码 代码如下: if (true) { var i = 100; } alert(i); //弹出框并显示100 很多现代语言都推荐尽可能迟地声明变量,但在Javascript里这是一个最糟糕的建议。由于缺少块级作用域,最好在函数体的顶部声明函数中可能用到的所有变量。 闭包特性: 虽然缺少块级作用域,但是函数的作用域还是存在的。 这种作用域有一个好处,就是内部函数可以访问定义它们的外部函数的参数和变量(除了this和argument)。 利用这种特性,则可以这样来设计代码。 复制代码 代码如下: var bankAccount = function () { var value = 0; return { deposit: function (inc) { value += inc; }, getValue: function (){ return value; } } } var myAccount = bankAccount(); //新开一个银行账户 myAccount.deposit(1000); //存1000块进去 alert(myAccount.getValue()); //should alert(1000); value由于在bankAccount这个function里,外部无法对它进行直接操作,必须通过bankAccount function给他返回的对象来进行操作,通过这样来实现C#和java里的private的字段。 减缓全局变量污染全局空间:利用函数的作用域,我们在写js库的时候可以减少跟其他库冲突。 复制代码 代码如下: (function () { var hello = 'Hello World.'; })(); alert(hello); //error: hello no exist. 这里的语法很有点诡异,主要思想是定义一个匿名方法,并且马上执行。由于function开头这个litertal会被解释作为函数定义,这里加上了一对括号包住它,然后再用一对括号表示调用此函数。外部的alert访问不到在函数内部定义的hello。 陷阱一:var的陷阱 “减缓全局变量污染全局空间”的例子改成 复制代码 代码如下: (function () { hello = 'Hello World.'; //remove var })(); alert(hello); //alert ('Hello World.'); 当变量hello没有用var显式声明时,hello成为了一个全局变量!! 虽然利用这个特性,咱们可以提供一个对外接口,但不建议这样做。 复制代码 代码如下: (function () { var hello = 'Hello World.'; sayHello = function () { //不建议采用这种方式来提供接口,看起来很不明显。 alert(hello); } })(); sayHello(); 可以改进为 复制代码 代码如下: (function (window) { var hello = 'Hello World.'; window.$ = { sayHello: function () { alert(hello); } }; })(window); $.sayHello(); //看起来像jQuery那么酷 或 复制代码 代码如下: var obj = (function () { var hello = 'Hello World.'; return { sayHello: function () { alert(hello); } }; })(); obj.sayHello(); 陷阱二: 闭包的陷阱 复制代码 代码如下: (function () { //函数a var arr = [];   var i = 0; var j; for ( ; i < 3; i++) { arr.push(function () { //函数b alert(i * 10); }); } for (j in arr) { arr[j](); } })(); 原以为函数数组arr里各个函数执行后,会弹出0,10,20,但是结果不是如此。结果是弹出30,30,30。 函数b访问的不是当时的 i的值, 而是直接访问变量i(用于都是取i最新的值)。 原因是函数b是函数a的内部函数,变量i对函数b是可见的,函数b每次都从i处获取最新的值。 这次改成: 复制代码 代码如下: (function () { //函数a var arr = []; var i = 0;   var j; for ( ; i < 3; i++) { arr.push((function (anotherI) { //函数m return function () { //函数b alert(anotherI * 10); } })(i)); // 此处为(function b(anotherI) {})(i) } for (j in arr) { arr[j](); } })(); 这次执行后,终于弹出0,10,20。这是为什么呢。 函数b访问的是anotherI(当时的i的值),而不是直接访问变量i。 每次在arr.push前,都会定义一个新匿名的函数m。本例中定义了3个匿名函数m0,m1,m2,每当被调用后,他们的anotherI都得到当前i的值。每个m函数执行后都返回一个b函数。b0在m0里,b1在m1里,b2在m2里。b0只能访问m0的anotherI(为0),而b0访问不了m1的anotherI,因为m0和m1为不同的函数。

  推荐阅读

  xml文档转换工具,附图表例子(hta)

源文档,饼图数据 复制代码 代码如下: <?xml version="1.0" encoding="utf-8"?> <items> <title>各指标所占比重</title> <unit>人</unit> <item> <name>指标一</name> <value>50</value> <description>1</descript>>>详细阅读


本文标题:JavaScript.The.Good.Parts阅读笔记(二)作用域&闭包&减缓全局空间污染

地址:http://www.17bianji.com/kaifa2/JS/25432.html

关键词: 探索发现

乐购科技部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与乐购科技进行文章共享合作。

网友点评
自媒体专栏

评论

热度

精彩导读
栏目ID=71的表不存在(操作类型=0)