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