javascript closure(闭包)的一个示例
今天一个同事看到John Resig 的Pro JavaScript Techniques这本书上的37页上有一段关于闭包的javascript代码,怎么调试都运行不正确,于是和他一起研究了一下,代码是这样的:
1
// Create a new user object that accepts an object of properties
2
function User( properties ) {
3
// Iterate through the properties of the object, and make sure
4
// that it's properly scoped (as discussed previously)
5
for ( var i in properties ) {
6
(function(){
7
//using this here is wrong 这里用this是错误的,因为这时this的作用域是匿名函数的
8
// Create a new getter for the property
9
this[ "get" + i ] = function() {
10
//这里用properties[i]也是错误的,因为properties[i]作用域是在闭包的外面
11
return properties[i];
12
};
13
// Create a new setter for the property
14
this[ "set" + i ] = function(val) {
15
properties[i] = val;
16
};
17
})(); }
18
}
19
// Create a new user object instance and pass in an object of
20
// properties to seed it with
21
var user = new User({
22
name: "Bob",
23
age: 44
24
});
25
// Just note that the name property does not exist, as it's private
26
// within the properties object
27
alert( user.name == null );
28
// However, we're able to access its value using the new getname()
29
// method, that was dynamically generated
30
alert( user.getname() == "Bob" );
31
// Finally, we can see that it's possible to set and get the age using
32
// the newly generated functions
33
user.setage( 22 );
34
alert( user.getage() == 22 );
// Create a new user object that accepts an object of properties 2
function User( properties ) { 3
// Iterate through the properties of the object, and make sure 4
// that it's properly scoped (as discussed previously) 5
for ( var i in properties ) { 6
(function(){ 7
//using this here is wrong 这里用this是错误的,因为这时this的作用域是匿名函数的 8
// Create a new getter for the property 9
this[ "get" + i ] = function() {10
//这里用properties[i]也是错误的,因为properties[i]作用域是在闭包的外面11
return properties[i]; 12
}; 13
// Create a new setter for the property 14
this[ "set" + i ] = function(val) { 15
properties[i] = val; 16
}; 17
})(); } 18
} 19
// Create a new user object instance and pass in an object of 20
// properties to seed it with 21
var user = new User({ 22
name: "Bob", 23
age: 44 24
}); 25
// Just note that the name property does not exist, as it's private 26
// within the properties object 27
alert( user.name == null ); 28
// However, we're able to access its value using the new getname() 29
// method, that was dynamically generated 30
alert( user.getname() == "Bob" ); 31
// Finally, we can see that it's possible to set and get the age using 32
// the newly generated functions 33
user.setage( 22 ); 34
alert( user.getage() == 22 );
这段代码应该是有几处错误的,如红色字体所示,this的作用域是匿名函数的;另一处是properties[i],它的scope是匿名函数外面,所以,代码执行将会不正确。
经过一番调试,应该写成这样:
1
function User( properties ) {
2
//这里一定要声明一个变量来指向当前的instance
3
var objthis = this;
4
for ( var i in properties ) {
5
(function(){
6
//在闭包内,t每次都是新的,而 properties[i] 的值是for里面的
7
var t = properties[i];
8
objthis[ "get" + i ] = function() {return t;};
9
objthis[ "set" + i ] = function(val) {t = val;};
10
})();
11
}
12
}
13
14
//测试代码
15
var user = new User({
16
name: "Bob",
17
age: 44
18
});
19
20
alert( user.getname());
21
alert( user.getage());
22
23
user.setname("Mike");
24
alert( user.getname());
25
alert( user.getage());
26
27
user.setage( 22 );
28
alert( user.getname());
29
alert( user.getage());
function User( properties ) { 2
//这里一定要声明一个变量来指向当前的instance 3
var objthis = this; 4
for ( var i in properties ) { 5
(function(){ 6
//在闭包内,t每次都是新的,而 properties[i] 的值是for里面的 7
var t = properties[i]; 8
objthis[ "get" + i ] = function() {return t;}; 9
objthis[ "set" + i ] = function(val) {t = val;}; 10
})(); 11
} 12
} 13
14
//测试代码 15
var user = new User({ 16
name: "Bob", 17
age: 44 18
}); 19
20
alert( user.getname()); 21
alert( user.getage()); 22
23
user.setname("Mike"); 24
alert( user.getname()); 25
alert( user.getage()); 26
27
user.setage( 22 ); 28
alert( user.getname()); 29
alert( user.getage());
这样,代码就是按预想的执行了。
ps: blog搬家,欢迎访问新地址:www.jinweijie.com



浙公网安备 33010602011771号