在javascript中动态创建get/set方法

Don*_* Ch 6 javascript oop

我正在尝试创建一个UserDon对象,并尝试以编程方式生成get和set方法(基于John Resig第37页的Pro Javascript书),并在Firefox 3.5上测试它

问题是:在函数UserDon中,"this"指的是窗口对象而不是UserDon对象.

所以在调用var userdon = new UserDon(...)之后,我在window对象上创建了setname和getname方法(也是setage和getage).

我怎样才能解决这个问题?

function UserDon( properties ) {
   for( var i in properties ) {
   (function(){
      this[ "get" + i ] = function() {
        return properties[i];
      };

      this[ "set" + i ] = function(val) {
        properties[i] = val;
      };
      })();
   }
 }

var userdon = new UserDon( {
   name: "Bob",
   age: 44
});
Run Code Online (Sandbox Code Playgroud)

CMS*_*CMS 7

this您使用的值属于循环内部的自动调用函数表达式,当您以这种方式调用函数时,this始终引用全局对象.

编辑:我错过了函数表达式尝试进行变量捕获以处理循环内的getter/setter创建这一事实,但循环变量i需要作为参数传递才能执行此操作并且因为函数表达式是在那里,this应该保留上下文(外部):

function UserDon( properties ) {
  var instance = this; // <-- store reference to instance

  for( var i in properties ) { 
    (function (i) { // <-- capture looping variable
      instance[ "get" + i ] = function() {
        return properties[i];
      };

      instance[ "set" + i ] = function(val) {
        properties[i] = val;
      };
    })(i); // <-- pass the variable
  }
}

var userdon = new UserDon( {
   name: "Bob",
   age: 44
});

userdon.getname(); // "Bob"
userdon.getage();  // 44
Run Code Online (Sandbox Code Playgroud)

您还可以使用该call方法调用函数表达式,保留上下文(值this)并在一个步骤中将循环变量引入新作用域:

function UserDon( properties ) {
  for( var i in properties ) { 
    (function (i) { // <-- looping variable introduced
      this[ "get" + i ] = function() {
        return properties[i];
      };

      this[ "set" + i ] = function(val) {
        properties[i] = val;
      };
    }).call(this, i); // <-- preserve context and capture variable
  }
}
Run Code Online (Sandbox Code Playgroud)

我还建议if (properties.hasOwnProperty(i)) { ... }for...in循环内部使用,以避免迭代继承自的用户扩展属性Object.prototype.