(例子来自书,但我似乎没有得到它)
function User (properties){
for( var i in properties){
(function(){
this["get"+i] = function () { return properties[i];};
this["set"+i] = function (valueOne) { properties[i] = valueOne; };
}) ();
}// END for
}// END User
var userOne = new User ({ name: "Billy", age: 35 });
userOne.getname();
当我运行此操作时,用户没有getname
方法。如何使特权方法有效?
答案 0 :(得分:3)
您需要在闭包中捕获this
和i
:
function User (properties){
for( var i in properties){
(function(t, i){
t["get"+i] = function () { return properties[i];};
t["set"+i] = function (valueOne) { properties[i] = valueOne; };
}) (this, i);
}// END for
}// END User
答案 1 :(得分:2)
this
不是你认为的那个人。由于您在没有任何情况下调用了IIFE,this
将成为全局范围,因此窗口将获取方法getname
等,这不是您所期望的。
要修复它,如果你想保留IIFE,你需要在正确的背景下调用它:
function User (properties){
for( var i in properties){
(function(key){
this["get"+key] = function () { return properties[key];};
this["set"+key] = function (valueOne) { properties[key] = valueOne; };
}).call(this, i);
}// END for
}// END User
var userOne = new User ({ name: "Billy", age: 35 });
userOne.getname();
请注意,您也忘记将i
参数传递给函数并将其解释为参数。否则所有函数都将绑定到同一个键,因此userOne.getname
将返回35。
答案 2 :(得分:1)
这是因为你使用了一个立即调用的函数
for( var i in properties){
(function(){ //<--- This
this["get"+i] = function () { return properties[i];};
this["set"+i] = function (valueOne) { properties[i] = valueOne; };
}) ();
}
删除它仍然无效,但您的方法将在那里。要使其完全正常运行,您应该保留i
for( var i in properties){
(function(i){ //<--- This
this["get"+i] = function () { return properties[i];};
this["set"+i] = function (valueOne) { properties[i] = valueOne; };
}) (i); //<--- and this
}
后一个问题与第一个问题不同(尽管有关)。
Javascript只有所谓的“功能范围”,这意味着限制功能范围的唯一因素是......好吧......一个功能。因此,一个常见的模式是在for循环内或在许多你不希望变量泄漏的地方使用这样的IIFE。
但是,javascript中的this
参数很奇怪。了解以下内容,它将为您节省吨的麻烦:javascript中的 this
与任何其他参数没有区别。
让我解释一下。
有四种方法可以在javascript中调用函数。
myFn.call("this param", "param 1", "param 2"); //this is "this param"
myFn.apply("this param", ["param 1", "param 2"]); //this is "this param"
myFn("param 1", "param 2");
//javascript takes a guess at what `this` should be -
//usually it is set to the global `window`.
new myFn("param 1", "param 2");
//`this` is a new function with its' prototype set to myFn.prototype
如果您总是使用.call
表单,则所有歧义都将消失,您可以看到this
与其他所有参数完全相同。然而,这是额外的语法,人们更喜欢使用更简单的形式,这意味着你必须考虑什么是“这”的规则。
因此,您在示例中所做的是在全局window
对象上放置getter和setter。
我要在这里发表一个声明,你的书可能不同意,但我已经从多年的学习,工作和教学javascript中学到了:
请勿使用new
和this
关键字。
这两个关键词在JS中引入了大量的概念,这些概念令人困惑并且确实存在 - 除非你正在制作非常性能敏感的东西(你不是,我知道你认为你是,但是你'不是) - 没必要。而是像这样创建新对象:
var user = { name: "Billy", age: 35 };
如果您绝对必须拥有getter和setter,那么这样做:
function createObjectWithProps (properties){
var obj = {};
var state = {}[
for( var k in properties){
(function(key) {
obj["get"+key] = function () { return state[key];};
obj["set"+key] = function (valueOne) { state[key] = valueOne; };
})(k)
}
return obj;
}
var userOne = createObjectWithProps ({ name: "Billy", age: 35 });
userOne.getname();
虽然我会更进一步说明getter和setter在js中并不是非常有用,当你使用它们时,遵循类似于knockout的模式是标准的。
答案 3 :(得分:-1)
问题是“this”关键字。
因为您在立即调用的函数中使用它,所以它指向全局范围。
试试这个:
function User (properties){
for( var i in properties){
(function(self,i){
self["get"+i] = function () { return properties[i];};
self["set"+i] = function (valueOne) { properties[i] = valueOne; };
}) (this,i);
}// END for
}// END User