特权方法 - 如何获取传递给函数的属性值?

时间:2014-01-22 16:23:11

标签: javascript privileged-functions

(例子来自书,但我似乎没有得到它)​​

    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 个答案:

答案 0 :(得分: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

答案 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中学到了:

请勿使用newthis关键字。

这两个关键词在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