今天一个同事看到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)
5for ( 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 );
2 function User( properties ) {
3// Iterate through the properties of the object, and make sure
4// that it's properly scoped (as discussed previously)
5for ( 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());
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