参考资料:
http://xlaaa111.iteye.com/blog/669421
http://www.iteye.com/topic/296492
http://www.iteye.com/topic/305248
http://apps.hi.baidu.com/share/detail/8489632
http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
http://blog.belltoy.net/javascript_scope_call_object_closure.html
其中,有些地方不大理解
http://xlaaa111.iteye.com/blog/669421 写道
本段中提到了两个重要的词语:函数的定义与执行。文中提到函数的作用域是在定义函数时候就已经确定,而不是在执行的时候确定(参看步骤1和3)。用一段代码来说明这个问题:
function f(x) {
var g = function () { return x; }
return g;
}
var h = f(1);
alert(h());这段代码中变量h指向了f中的那个匿名函数(由g返回)。
假设函数h的作用域是在执行alert(h())确定的,那么此时h的作用域链是:h的活动对象->alert的活动对象->window对象。
假设函数h的作用域实在定义时确定的,就是说h指向的那个匿名函数在定义的时候就已经确定了作用域。那么在执行的时候,h的作用域链为:h的活动对象->f的活动对象->window对象。
如果第一种假设成立,那输出值就是undefined;如果第二种假设成立,输出值则为1。
运行结果证明了第2个假设是正确的,说明函数的作用域确实是在定义这个函数的时候就已经确定了。
function f(x) {
var g = function () { return x; }
return g;
}
var h = f(1);
alert(h());这段代码中变量h指向了f中的那个匿名函数(由g返回)。
假设函数h的作用域是在执行alert(h())确定的,那么此时h的作用域链是:h的活动对象->alert的活动对象->window对象。
假设函数h的作用域实在定义时确定的,就是说h指向的那个匿名函数在定义的时候就已经确定了作用域。那么在执行的时候,h的作用域链为:h的活动对象->f的活动对象->window对象。
如果第一种假设成立,那输出值就是undefined;如果第二种假设成立,输出值则为1。
运行结果证明了第2个假设是正确的,说明函数的作用域确实是在定义这个函数的时候就已经确定了。
这个地方需要注意:
http://www.iteye.com/topic/296492 写道
var scope = "global" //定义全局变量
function print() {
alert(scope);
}
function change() {
var scope = "local"; //定义局部变量
print(); //虽然是在change函数的作用域内调用print函数,
//但是print函数执行时仍旧按照它 定义时的作用域起作用
}
change(); //golbal
function print() {
alert(scope);
}
function change() {
var scope = "local"; //定义局部变量
print(); //虽然是在change函数的作用域内调用print函数,
//但是print函数执行时仍旧按照它 定义时的作用域起作用
}
change(); //golbal
这个例子不错,可以参考,整理下思路
http://www.iteye.com/topic/296492 写道
来看一个利用闭包来模拟私有属性的例子
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
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
作用域链的解释:在定义的时候就已经确定
http://www.iteye.com/topic/305248 写道
function f1(){var a=1;f2();}
function f2(){return a;}
f1();//a没有定义
先看看函数f1,调用了函数f2,因为函数局部变量a也在f1中,可能期望函数f2也访问a,但事实却不是这样。
因为这个时候f2函数已经定义完毕了,而它的范围没有a被找到。不管是函数f1还是函数f2,仅仅能访问的是本身的局部变 量或者全局变量。
function f2(){return a;}
f1();//a没有定义
先看看函数f1,调用了函数f2,因为函数局部变量a也在f1中,可能期望函数f2也访问a,但事实却不是这样。
因为这个时候f2函数已经定义完毕了,而它的范围没有a被找到。不管是函数f1还是函数f2,仅仅能访问的是本身的局部变 量或者全局变量。
不过还是不大理解作用域和执行环境,下面这两个例子就不是很理解
http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html 写道
代码片段一。
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()());
代码片段二。
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()());
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()());
代码片段二。
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()());