js一段代码 在线等!!!

wis2007 2009-09-10 10:47:00
<script language="javascript">
function User( properties ) {
//遍历对象属性,确保它作用域正确
for ( var i in properties ) { (function(which){ var p=i
//为属性创建获取器
which[ "get" + i ] = function() {
return properties[p];
};
//为属性创建设置器
which[ "set" + i ] = function(val) {
properties[p] = val;
};
})(this); }
}
var user = new User({
name: "Bob",
age: 44
});
alert( user.name == null );
alert( user.getname() == "Bob" );
user.setage( 22 );
alert( user.getage() == 22 );
</script>


那位大哥 仔细讲讲User 函数中which 的作用吗?
还有var p=i 去掉 其他的p改为i 怎么结果就不对了呢?
在线等!!!!
...全文
146 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
li1229363 2009-09-12
  • 打赏
  • 举报
回复
楼上的老大,咱膜拜下!
bfcady 2009-09-10
  • 打赏
  • 举报
回复
确实是闭包引起的,我是这样理解的。。。

方法function(which)是用来给user添加属性访问器

对于properties的每一个属性,方法function(which)都会声明且执行一次,
其中传递给which的实参是user本身。

假设将语句 return properties[p]; 改成 return properties[i];

对于第一次迭代 which["get" + i] 语句都会给user添加一个方法user.getname(),这并没有什么疑问,
但对于这个方法的方法体,解析器只是解析,并不执行,其中的i会是一个变量引用。

当迭代完成,匿名方法function(which)的外部变量i的值会是迭代的最后一个属性名,也就是age。
那么当你调用user.getname()时,依然会返回属性age的值,也就是44.
li1229363 2009-09-10
  • 打赏
  • 举报
回复
在调用user的时候,自动的调用了which。

每次调用的时候,执行一次操作。

那么for中的i是如何存在的呢?

如果你第一次访问user的时候,会由于user设定了name、age两个参数而进行初始化。而i是连续给与赋值的。i保存的永远是最后一个参数的名称

所以为了保存第一个i,只好用了p这个变量了。


function User( properties ) {
//遍历对象属性,确保它作用域正确
for ( var i in properties ) { alert(i);(function(which){ var p=i
//为属性创建获取器
which[ "get" + i ] = function() {
alert(i+" "+p)
return properties[p];
};
//为属性创建设置器
which[ "set" + i ] = function(val) {
alert(i+" "+p)
properties[p] = val;
};
})(this); }
}
var user = new User({
name: "Bob",
age: 44,
sex:"man"
});
//alert( user );
alert( user.getname() );
alert( user.getage() );
//user.setage( 22 );
shiyoumaomao 2009-09-10
  • 打赏
  • 举报
回复
学习学习。。。
toury 2009-09-10
  • 打赏
  • 举报
回复

<script>
function User(properties){
//遍历对象属性,确保它作用域正确
for (var i in properties){
(
function(wis2007){//这个which是闭包传进的参数this,随便你用什么名,例如换成wis2007
alert(i)//加这句就清楚了
var p=i
//为属性创建获取器 <-----说的很清楚了。其实就是给this创建一个方法
wis2007["get"+i]=function(){
//之所以要将i赋值给p是闭包要求。
return properties[p];//properties[p]是当前的属性
//////////return properties[i];//properties[i]是最后一个属性age了
};
//为属性创建设置器<-----说的很清楚了。其实就是给this创建一个方法
wis2007["set"+i]=function(val){
properties[p]= val;
};
}
)(this);
}
}

var user = new User({
name: "Bob",
age: 44
});

alert( 'user.name是null吗?\n\n'+(user.name == null) );
alert( '用新创建的user.getname()获得的是"Bob"吗?\n\n'+(user.getname() == "Bob") );
user.setage( 22 );
alert('用新创建的user.setage()获得的是22吗?\n\n'+ (user.getage() == 22) );

</script>
wis2007 2009-09-10
  • 打赏
  • 举报
回复
大哥们,谢谢。我研究下,一会结贴。
BeenZ 2009-09-10
  • 打赏
  • 举报
回复
不是也许是对的,是说错了...纠正下
which 是用来绑定事件对象的,这里指向User.
li1229363 2009-09-10
  • 打赏
  • 举报
回复
如果是闭包

第一次执行的时候,p与i不相等。所以,如果不把这个时候的i保存下来,就会丢失掉i
li1229363 2009-09-10
  • 打赏
  • 举报
回复
楼上的可能是对的。

咱也在研究中。
BeenZ 2009-09-10
  • 打赏
  • 举报
回复
用p=i的理由
执行下面测试

<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title> </title>
<style>

</style>
<script>


function User( properties ) {
//遍历对象属性,确保它作用域正确
for ( var i in properties ) { (function(which){
var p=i
//为属性创建获取器
which[ "get" + i ] = function() {
alert(i+" "+p)
return properties[p];
};
//为属性创建设置器
which[ "set" + i ] = function(val) {
properties[p] = val;
};
})(this); }
}
var user = new User({
name: "Bob",
age: 44
});
alert(user.getname() == "Bob" )
/*alert( user.name == null );
user.getname() == "Bob"
user.setage( 22 );
alert( user.getage() == 22 );*/

window.onload=function(){


}
</script>
</head>
<body>


<div class="news_dh" id=aaa>
<TEXTAREA NAME="mytxt" ROWS="5" COLS="25" WRAP="soft" ID="Textarea1"> </TEXTAREA>

</div>

</body>
</html>


产生这种现象的原因是闭包
BeenZ 2009-09-10
  • 打赏
  • 举报
回复
说错,不是i的值,是User[i]
BeenZ 2009-09-10
  • 打赏
  • 举报
回复
which是匿名内部函数的参数.也就是for循环中i的值
toury 2009-09-10
  • 打赏
  • 举报
回复
另外,对于你一直不明白的var p=i的问题(闭包问题),可以改成如下写法,就不用p=i了:

<body>
<div id=aaa></div>
</body>

<script>
function User(properties){
J++;
sHTML +="2、当你new一个User()对象的实例 “user”时,User()对象开始初始化;<br>" ;

var cycleCount=0;//为了解释增加该变量
for (var i in properties){//遍历对象属性,确保它作用域正确
cycleCount++
J++;
sHTML +=J+"、进入遍历对象属性的循环内;属性名为"+i+"<br>" ;
/*************************注意这段代码,是一个立即执行的匿名函数**********************************/

(
function(wis2007,p){
//第一个参数是是闭包传进的参数this,随便你用什么名,例如换成wis2007
//第二个参数就是for循环中的i.传参进来就可以不用var p=i了,这就解决了闭包的问题。当然参数名可以随便取,只要下面相应的更改就可以了
J++;
sHTML +=J+"、进入立即执行的匿名函数;参数wis2007就是传进的this(this指的是你调用User()的对象,就是刚new出来的user),<br>随便你用什么名,例如换成which<br>" ;
sHTML +="第二个参数就是for循环中的i,传参进来就可以不用var p=i了,这就解决了闭包的问题。当然参数名可以随便取,只要下面做相应的更改就可以了<br>"

//////////////////////var p=i

J++;
sHTML +=J+"、为属性创建获取器 <-----说的很清楚了。其实就是给this创建一个get"+p+"方法<br>" ;

wis2007["get"+i]=function(){
J++;
sHTML +=J+"、调用创建的user.get"+p+"()方法获取"+p+"的值<br>" ;

return properties[p];//properties[p]是当前的属性
};

J++;
sHTML +=J+"、为属性创建获取器 <-----说的很清楚了。其实就是给this创建一个set"+p+"方法<br>" ;

wis2007["set"+i]=function(val){
J++;
sHTML +=J+"、调用创建的user.set"+p+"()方法设置"+p+"的值<br>" ;

properties[p]= val;
};
}
)(this,i); //参数this指的是你调用User()的对象,就是刚new出来的user;此处将它传参进入匿名函数
//参数 i是循环的参数i,在这里和this一起传入匿名函数,可解决vai p=i的问题。

/**********************************************************************************************/

}
}
debugger
//为了演示JS执行步骤,加了个DIV
var sHTML='';
var J=1//为了解释,增加J变量

sHTML +=J+"、new一个User()对象的实例 “user”,它的参数是{name: \"Bob\", age: 44};<br>"
var user = new User({
name: "Bob",
age: 44
});

J++;
sHTML +="<br><br>"+J+"、初始化结束,开始使用创建的方法;<br>" ;

alert( 'user.name是null吗?\n\n'+(user.name == null) );
alert( '用新创建的user.getname()获得的是"Bob"吗?\n\n'+(user.getname() == "Bob") );
user.setage( 22 );
alert('用新创建的user.setage()获得的是22吗?\n\n'+ (user.getage() == 22) );

document.getElementById("aaa").innerHTML=sHTML;
</script>


有关闭包的问题,请自己找本书看看,一句话两句话说不清。呵呵

还有另外一个方法我就不写了,累了。哪位有兴趣可以写出来。
toury 2009-09-10
  • 打赏
  • 举报
回复
拷贝下面的代码,最好在IE中运行一下,可进入调试状态,然后F11单步跟踪一下,你就明白了

<body>
<div id=aaa></div>
</body>

<script>
function User(properties){
J++;
sHTML +="2、当你new一个User()对象的实例 “user”时,User()对象开始初始化;<br>" ;

var cycleCount=0;//为了解释增加该变量
for (var i in properties){//遍历对象属性,确保它作用域正确
cycleCount++
J++;
sHTML +=J+"、进入遍历对象属性的循环内;属性名为"+i+"<br>" ;
/*************************注意这段代码,是一个立即执行的匿名函数**********************************/

(
function(wis2007){//这个参数是是闭包传进的参数this,随便你用什么名,例如换成wis2007
J++;
sHTML +=J+"、进入立即执行的匿名函数;参数wis2007就是传进的this(this指的是你调用User()的对象,就是刚new出来的user),<br>随便你用什么名,例如换成which<br>" ;

J++;
sHTML +=J+"、保存第"+cycleCount+"个属性到变量p("+p+")<br> (如果不保存,则属性是"+i+")<br>" ;
var p=i

J++;
sHTML +=J+"、为属性创建获取器 <-----说的很清楚了。其实就是给this创建一个get"+i+"方法<br>" ;

wis2007["get"+i]=function(){

J++;
sHTML +=J+"、调用创建的user.get"+p+"()方法获取"+p+"的值<br>" ;

return properties[p];//properties[p]是当前的属性
///////return properties[i];//properties[i]是最后一个属性age了
};

J++;
sHTML +=J+"、为属性创建获取器 <-----说的很清楚了。其实就是给this创建一个set"+i+"方法<br>" ;

wis2007["set"+i]=function(val){
J++;
sHTML +=J+"、调用创建的user.set"+p+"()方法设置"+p+"的值<br>" ;

properties[p]= val;
};
}
)(this); //参数this指的是你调用User()的对象,就是刚new出来的user;此处将它传参进入匿名函数

/**********************************************************************************************/
J++;
sHTML +=J+"、<font color=blue>这里的i值是第"+cycleCount+"个属性"+i+";</font><br>" ;

}
J++;
sHTML +=J+"、<font color=red>注意!!这里的i值是"+i+";调用getname方法时,由于i是"+i+",所以return properties[i]就变成return properties['"+i+"']了。<br> 这就是为什么要var p=i的原因了</font><br>" ;
}
debugger
//为了演示JS执行步骤,加了个DIV
var sHTML='';
var J=1//为了解释,增加J变量

sHTML +=J+"、new一个User()对象的实例 “user”,它的参数是{name: \"Bob\", age: 44};<br>"
var user = new User({
name: "Bob",
age: 44
});

J++;
sHTML +="<br><br>"+J+"、初始化结束,开始使用创建的方法;<br>" ;

alert( 'user.name是null吗?\n\n'+(user.name == null) );
alert( '用新创建的user.getname()获得的是"Bob"吗?\n\n'+(user.getname() == "Bob") );
user.setage( 22 );
alert('用新创建的user.setage()获得的是22吗?\n\n'+ (user.getage() == 22) );

document.getElementById("aaa").innerHTML=sHTML;
</script>

wis2007 2009-09-10
  • 打赏
  • 举报
回复
大哥们,小妹初次接触还不是很明白,有劳再仔细讲讲!!!

Mr_BeasonZhou 2009-09-10
  • 打赏
  • 举报
回复
学习学习!!!!!
wis2007 2009-09-10
  • 打赏
  • 举报
回复
toury 大哥 “//之所以要将i赋值给p是闭包要求。” 闭包都有什么要求呢?
wis2007 2009-09-10
  • 打赏
  • 举报
回复
li1229363 大哥,为什么p与i不等呢?

87,907

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧