我有一个带有 getter 和 setter 的 Object
,我打算在其中保护一个属性,以便它只能通过一种方法进行更新。我们称此对象为 Person
,它具有以下结构:
function Person(data) {
var _name = data.name;
this.name = function () {
return _name;
};
this.setName = data.setName || function (newValue) {
_name = newValue;
};
}
我希望能够覆盖 setName
并将不同的实现传递给 Person
的每个实例,但我似乎无法让它正常工作。我确定这是一个关闭问题,但我无法理解它。
鉴于以下使用场景,我做错了什么?
var p1 = new Person({
name: "Paul",
setName: function (newValue) {
this._name = newValue;
}
});
var p2 = new Person({ name: "Bob" });
p1.setName("Paul (updated)");
p2.setName("Bob (updated)");
p1
永远不会更新其值,因此始终是“Paul”,而 p2
会更新并变为“Bob(已更新)”。我希望能够创建尽可能多的 Person
实例,其中 some 有自己的 setName
和其他实例将只使用默认实例。
我试过将 data.setName
包装在这样的闭包中,并设置我的自定义 setName
以返回值:
this.setName = data.setName ? function () {
return (function (value) {
value = data.setName();
}(_name));
} : function (newValue) { _name = newValue; }
但我运气不好 - 我显然没有像我想的那样得到闭包!任何帮助总是感激。
codepen.io example here
最佳答案
this._name = newValue;
_name
是私有(private)变量,不是属性。无法在 this
上访问它。看看Javascript: Do I need to put this.var for every variable in an object?如果您不确定两者之间的区别。
function (value) { value = data.setName(); }
value
这里是该函数范围的局部变量,而不是对您传入的 _name
变量的“引用”。设置它只会将不同的值放入该局部变量,但不更改任何其他内容。
可能的解决方案:
将有权访问
_name
变量的 setter 函数传递给 验证器:function Person(data) { var _name = data.name; this.name = function () { return _name; }; if (data.nameValidator) this.setName = function(newValue) { _name = data.nameValidator(newValue, _name); }; else this.setName = function (newValue) { _name = newValue; }; } var p1 = new Person({ name: "Paul", nameValidator: function (newValue, oldValue) { return (newValue /* ... */) ? newValue : oldValue; } });
或者让验证器返回值:
function Person(data) { var _name = data.name; this.name = function () { return _name; }; this.setName = function (newValue) { _name = newValue; }; if (data.makeNameValidator) this.setName = data.makeNameValidator(this.setName); } var p1 = new Person({ name: "Paul", makeNameValidator: function (nameSetter) { return function(newValue) { if (newValue) // ... nameSetter(newValue); }; } });
或者使
_name
成为验证器可以写入的属性。您也可以将它放在原始的data
对象上,以免将其暴露在Person
接口(interface)上:function Person(data) { this.name = function () { return data.name; }; if (data.setName) this.setName = data.setName.bind(data); else this.setName = function(newValue) { _name = newValue; }; } var p1 = new Person({ name: "Paul", setName: function (newValue) { if (newValue) // ... this.name = newValue; } });
关于javascript - 覆盖对象上的 setter ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22934209/