我正在研究javascript,我遇到了与范围有关的问题。
这是代码
function User (properties) {
for (var i in properties) {
(function () {
this ['get' + i] = function () {
return properties [i];
};
}) ();
}
}
var me = new User ({
Id : 54,
Name : 'ohyou'
});
console.log (me.getName ());
console.log (me.getId ());
我希望它如何工作:它应该创建属于getName
对象的两个函数getId
和me
。
工作原理:它可以按照我的意愿创建两个函数,但它们属于window
我尝试了什么:
我尝试删除第3行的功能。它可以实现我想要的功能,但现在它返回name
" ohyou"两次,而不是返回id
和name
我尝试使用window
范围内的功能,问题与前一种情况一样持续存在 - 它会两次返回name
。
问题:我做错了什么,如何让它按我的意愿运作?
P.S。使用手机发布此帖子,抱歉可能存在拼写错误或格式问题。另外,请原谅我的英语技能。
答案 0 :(得分:2)
尝试理解以下代码的工作原理:
function User(properties) {
for (var i in properties) {
with ({ i: i, self: this, props: properties }) {
self["get" + i] = function () {
return props[i];
};
}
}
}
var me = new User({
Id: 54,
Name: "ohyou"
});
alert(me.getName());
alert(me.getId());

这是with
声明的合法用法之一。
我发现with
语句比使用其他人建议的立即调用的函数表达式(IIFE)更简洁。
修改:如果您正确使用,with
关键字也不错。有一些合法用途:
http://webreflection.blogspot.in/2009/12/with-worlds-most-misunderstood.html
您的代码无法正常工作的原因是因为每个函数都拥有自己的this
值。因此,当您在for
循环中立即调用函数表达式时,函数内的this
值不再是您的新对象。它是window
。要解决这个问题,您可以执行以下操作:
(function (i, self, props) {
self["get" + i] = function () {
return props[i];
};
}(i, this, properties))
但是使用with
语句干净且速度更快。它更快,因为你没有调用函数。
答案 1 :(得分:2)
function User (properties) {
var that = this;
for (var i in properties) {
(function (i) {
that ['get' + i] = function () {
return properties [i];
};
}) (i);
}
}
var me = new User ({
Id : 54,
Name : 'ohyou'
});
答案 2 :(得分:2)
如果您使用Object.keys
然后forEach
已经引入了新范围,则可以避免所有这些闭包和其他内容。然后,您必须传递this
值,这是第二个参数:
function User(properties) {
Object.keys(properties).forEach(function(k) {
this['get'+ k] = function() {
return properties[k]
}
},this)
}
答案 3 :(得分:0)
您必须记住的一件事是,任何不属于任何对象的函数都将永远属于窗口对象。
例如,如果我们修改您的对象并添加新方法,
me.doSomeWork = function(){
this.myLuckyNumber = 10;
var that = this;
function doubleMyLuckyNumber(){
console.log(this); //window
that.myLuckyNumber = that.myLuckyNumber * 2;
}
doubleMyLuckyNumber();
};
me.doSomeWork();
console.log(me.myLuckyNumber) //outputs 20
因此,始终将引用保存到 var 以在内部方法中使用它。您可以使用其他人建议的任何方式,但我更喜欢James emanon的方法。