Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/474.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在javascript中动态创建get/set方法_Javascript_Oop - Fatal编程技术网

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

在javascript中动态创建get/set方法,javascript,oop,Javascript,Oop,我正在尝试创建一个UserDon对象,并尝试以编程方式生成get和set方法(基于John Resig的Pro Javascript书籍第37页),并在Firefox 3.5上对此进行测试 问题是:在函数UserDon中,“this”指的是窗口对象,而不是UserDon对象 因此,在调用var userdon=newuserdon(…)之后,我得到了在窗口对象上创建的setname和getname方法(也包括setage和getage) 我怎样才能解决这个问题 function UserDon(

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

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

因此,在调用var userdon=newuserdon(…)之后,我得到了在窗口对象上创建的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
});

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

Edit:我忽略了一个事实,即函数表达式试图捕获变量以处理循环内的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

我还建议在
for…in
循环中使用
if(properties.hasOwnProperty(I)){…}
,以避免迭代从
对象继承的用户扩展属性。prototype

最好是获得一个包含两个参数的通用函数:属性名称和值(或者只提供getter的名称)。
此函数将检查此属性是否存在特定函数,如果没有,则只需更改属性的值(或为getter返回其值)。

以下是我将如何对其进行编码:-

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

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

您也可以使用鲜为人知的
\uuuuu定义设置(“varName”,function(){});

\uuuu定义设置(“varName”,function(val){});

尽管它们是非标准的[如x-html-replace内容类型],但大多数非ie浏览器(chrome、firefox)都支持它们

语法将是:

benjamin = new object();
benjamin.__defineGetter__("age", function(){
  return 21;
});
或者你可以通过原型来实现这一点

benjamin = {
  get age()
  {
    return 21;
  }
}

如果这是一个练习,这是一个很好的问题。否则,如果您没有在getter/setter中执行任何其他操作,您希望只使用公共属性并放弃方法开销。:)如果没有自动调用函数,getname()和getage()都将返回44,因为闭包引用数组的最后一个值,即age,请参阅本书的第29页。@portoalet:你说得对,我错过了这一点,但这还不够,应将
I
变量作为参数传递给该函数,还应保留
this
值,请参见我的编辑。以前从未见过这种情况。您自己在使用它吗?我只使用它调试正在获取/设置变量的地方。您定义了setter(“variableName”,outputStackTrace);而且它也适用于css样式。例如,您说的是
object.style.\uuuuu defineGetter\uuuuuu(“左”,outputStackTraceFunction)由于某些原因,人们不知道此函数。可能是因为它不标准?
benjamin = {
  get age()
  {
    return 21;
  }
}