锁定老帖子 主题:javascript面向对象技术基础(六)
精华帖 (17) :: 良好帖 (2) :: 新手帖 (8) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-12-18
最后修改:2009-01-12
作用域、闭包、模拟私有属性 var sco = "global"; //全局变量 function t() { var sco = "local"; //函数内部的局部变量 alert(sco); //local 优先调用局部变量 } t(); //local alert(sco); //global 不能使用函数内的局部变量
注意一点,在javascript中没有块级别的作用域,也就是说在java或c/c++中我们可以用"{}"来包围一个块,从而在其中定义块内的局部变量,在"{}"块外部,这些变量不再起作用,同时,也可以在for循环等控制语句中定义局部的变量,但在javascript中没有此项特性: function f(props) { for(var i=0; i<10; i++) {} alert(i); //10 虽然i定义在for循环的控制语句中,但在函数 //的其他位置仍旧可以访问该变量. if(props == "local") { var sco = "local"; alert(sco); } alert(sco); //同样,函数仍可引用if语句内定义的变量 } f("local"); //10 local local
在函数内部定义局部变量时要格外小心: var sco = "global"; function print1() { alert(sco); //global } function print2() { var sco = "local"; alert(sco); //local } function print3() { alert(sco); //undefined var sco = "local"; alert(sco); local } print1(); //global print2(); //local print3(); //undefined local 前面两个函数都很容易理解,关键是第三个:第一个alert语句并没有把全局变量"global"显示出来,而是undefined,这是因为在print3函数中,我们定义了sco局部变量(不管位置在何处),那么全局的sco属性在函数内部将不起作用,所以第一个alert中sco其实是局部sco变量,相当于: function print3() { var sco; alert(sco); sco = "local"; alert(sco); } 从这个例子我们得出,在函数内部定义局部变量时,最好是在开头就把所需的变量定义好,以免出错。 var scope = "global" //定义全局变量 function print() { alert(scope); } function change() { var scope = "local"; //定义局部变量 print(); //虽然是在change函数的作用域内调用print函数, //但是print函数执行时仍旧按照它定义时的作用域起作用 } change(); //golbal
闭包 var i = 0; function getNext() { i++; return i; } alert(getNext()); //1 alert(getNext()); //2 alert(getNext()); //3
一直用getNext函数得到下一个整数,而后不小心或者故意的将全局变量i的值设为0,然后再次调用getNext,你会发现又从1开始了........这时你会想到,要是把i设置成一个私有变量该多好,这样只有在方法内部才可能改变它,在函数之外就没有办法修改了.下面的代码就是按照这个要求来做得,后面我们详细讨论。 function temp() { var i = 0; function b() { return ++i; } return b; } var getNext = temp(); alert(getNext()); //1 alert(getNext()); //2 alert(getNext()); //3 alert(getNext()); //4 因为我们平时所说的javascript绝大多数都是指的在客户端(浏览器)下,所以这里也不例外。在javascript解释器启动时,会首先创建一个全局的对象(global object),也就是"window"所引用的对象.然后我们定义的所有全局属性和方法等都会成为这个对象的属性.不同的函数和变量的作用域是不同的,因而构成了一个作用域链(scope chain).很显然,在javascript解释器启动时,这个作用域链只有一个对象:window(Window Object,即global object).
function Person(name, age) { this.getName = function() { return name; }; this.setName = function(newName) { name = newName; }; this.getAge = function() { return age; }; this.setAge = function(newAge) { age = newAge; }; } var p1 = new Person("sdcyst",3); alert(p1.getName()); //sdcyst alert(p1.name); //undefined 因为Person('类')没有name属性 p1.name = "mypara" //显示的给p1添加name属性 alert(p1.getName()); //sdcyst 但是并不会改变getName方法的返回值 alert(p1.name); //mypara 显示出p1对象的name属性 p1.setName("sss"); //改变私有的"name"属性 alert(p1.getName()); //sss alert(p1.name); //仍旧为mypara
定义了一个Person类,有两个私有属性name,age,分别定义对应的get/set方法。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-12-19
感谢楼主,你的系列文章我都好好看过。非常棒。
这篇讲闭包我彻底也明白了。我想对你最后一段说的, “解释闭包不是一件容易的事”,这话说的的确是。 看完后,我个人感觉,像是模式设计里面的,工厂方法。用于创建接口实例的函数。外部只能访问提供的接口。具体实现里用到的东西是不可见的。 |
|
返回顶楼 | |
发表时间:2008-12-19
理解了闭包真开心啊,谢谢楼主。严重同意楼上的话,“解释闭包不是一件容易的事“,↖(^ω^)↗加油
|
|
返回顶楼 | |
发表时间:2008-12-22
我的认识,
闭包就是用来控制消除局部对象名和全局对象名间的同名访问冲突或访问限制(私有访问)的. 如果在一段代码中,用到的对象担心和全局的对象名冲突,那可以用闭包, 如果在一段代码中,希望某个对象只被特定的代码访问(比如局部函数),那可以用闭包, 不过闭包肯定不只是这两点, 比如动态建立返回的函数其实也闭包,而且每次返回的都是不同的对象. |
|
返回顶楼 | |
发表时间:2008-12-25
http://softbbs.pconline.com.cn/9497825.html这文章还是不错的
|
|
返回顶楼 | |
发表时间:2008-12-26
zhaoweisgz 写道 http://softbbs.pconline.com.cn/9497825.html这文章还是不错的
里面给出的来源网址: http://www.knowsky.com/442121.html 广告多的?就像个广告牌。 |
|
返回顶楼 | |
发表时间:2008-12-26
hite 写道 zhaoweisgz 写道http://softbbs.pconline.com.cn/9497825.html这文章还是不错的 里面给出的来源网址: http://www.knowsky.com/442121.html 广告多的?就像个广告牌。 帅哥你观察挺仔细俄......当时就是因为这个所以我才没把原始地址给弄出来 |
|
返回顶楼 | |
发表时间:2008-12-31
http://www.felixwoo.com/blog/article.asp?id=294
这个地址更原始一些,带的图也在 |
|
返回顶楼 | |
发表时间:2009-01-04
最后修改:2009-01-04
我想说明一下,楼主漏掉了原书中很重要的一段话
贴中所说的: “闭包是拥有变量、代码和作用域的表达式.在javascript中,函数就是变量、代码和函数的作用域的组合体,因此所有 的函数都是闭包(JavaScript functions are a combination of code to be executed and the scope in which to execute them. This combination of code and scope is known as a closure in the computer science literature. All JavaScript functions are closures).” 这个只是之计算机术语上的闭包概念,而不是我们希望理解"闭包"概念。二者是有区别的,本书中作者想让我们知道的特定的”闭包“是指 漏掉的一段: "when a nested function is exported outside the scope in which it is defined. When a nested function is used in this way, it is often explicitly called a closure." 就是当一个内部函数暴露在它本身被定义的作用域之外的时候,这个特定的情况下我们称为"闭包"。所以这里有2个不同的包概念。 第一段那种泛指的,什么所有函数都是闭包,其实实际使用上毫无意义。有用的是第2中闭包。所以大家要加以区分。 |
|
返回顶楼 | |
发表时间:2009-01-05
olaola 写道 我想说明一下,楼主漏掉了原书中很重要的一段话
贴中所说的: “闭包是拥有变量、代码和作用域的表达式.在javascript中,函数就是变量、代码和函数的作用域的组合体,因此所有 的函数都是闭包(JavaScript functions are a combination of code to be executed and the scope in which to execute them. This combination of code and scope is known as a closure in the computer science literature. All JavaScript functions are closures).” 这个只是之计算机术语上的闭包概念,而不是我们希望理解"闭包"概念。二者是有区别的,本书中作者想让我们知道的特定的”闭包“是指 漏掉的一段: "when a nested function is exported outside the scope in which it is defined. When a nested function is used in this way, it is often explicitly called a closure." 就是当一个内部函数暴露在它本身被定义的作用域之外的时候,这个特定的情况下我们称为"闭包"。所以这里有2个不同的包概念。 第一段那种泛指的,什么所有函数都是闭包,其实实际使用上毫无意义。有用的是第2中闭包。所以大家要加以区分。 在这里我得道歉了.这句话我是故意漏掉的,因为我没有能力解释其中的原因。我解释不了原书中的意思:既然任何一个函数都是一个闭包,那为什么在js中只有当一个方法暴露在它定义域之外时才称为闭包?如果仅仅用js语言的特殊性来解释的话,我自己觉得是很没有说服力的,所以在这个地方我忽略了过去,只好用例子来说明。既然olaola提出来了了,那请哪位再继续深入的解释一下如何? |
|
返回顶楼 | |