0

(示例来自书中,但我似乎不明白)

    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方法。如何使特权方法起作用?

4

4 回答 4

3

您需要两者thisi在闭包中捕获:

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
于 2014-01-22T16:30:43.333 回答
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。

于 2014-01-22T16:30:54.017 回答
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。

但是,thisjavascript中的参数很奇怪。了解以下内容,它将为您省去很多麻烦:this在 javascript 中与任何其他参数没有什么不同

让我解释。

在 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与其他所有参数完全一样。然而,这是额外的语法,人们更喜欢使用更简单的形式,这意味着您必须考虑“this”的规则。

因此,您在示例中所做的是在全局window对象上放置 getter 和 setter。

我将在此声明您的书可能不同意,但我从多年的学习、使用和教学 javascript 中吸取了教训:

不要使用newandthis关键字。

这两个关键字在 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 中并不是非常有用,当你使用它们时,遵循类似于敲除的模式是标准的。

于 2014-01-22T16:27:28.583 回答
-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
于 2014-01-22T16:29:33.293 回答