nic*_*s_r 34 javascript prototype defineproperty
如您所知,我们可以使用JS定义getter和setter defineProperty().我试图扩展我的班级时遇到困难defineProperty().
这是一个示例代码:
我有一个必须添加到对象的字段数组
fields = ["id", "name", "last_login"]
Run Code Online (Sandbox Code Playgroud)
我还有一个将被修改的课程
var User = (function(){
// constructor
function User(id, name){
this.id = id
this.name = name
}
return User;
})();
Run Code Online (Sandbox Code Playgroud)
还有一个函数,它将使用类添加字段 defineProperty()
var define_fields = function (fields){
fields.forEach(function(field_name){
var value = null
Object.defineProperty(User.prototype, field_name, {
get: function(){ return value }
set: function(new_value){
/* some business logic goes here */
value = new_value
}
})
})
};
Run Code Online (Sandbox Code Playgroud)
运行后define_fields()我在我的实例中有我的字段User
define_fields(fields);
user1 = new User(1, "Thomas")
user2 = new User(2, "John")
Run Code Online (Sandbox Code Playgroud)
但这些属性的值是相同的
console.log(user2.id, user2.name) // 2, John
console.log(user1.id, user1.name) // 2, John
Run Code Online (Sandbox Code Playgroud)
defineProperty()在这种情况下,有没有办法正常工作?如果我理解问题是value对于每个类的实例变得相同但我无法实现如何解决它.提前感谢您的回答.
UPD: 这种方式抛出"RangeError:超出最大调用堆栈大小"
var define_fields = function (fields){
fields.forEach(function(field_name){
Object.defineProperty(User.prototype, field_name, {
get: function(){ return this[field_name] }
set: function(new_value){
/* some business logic goes here */
this[field_name] = new_value
}
})
})
};
Run Code Online (Sandbox Code Playgroud)
Tot*_*.js 52
请不要实现任何其他版本,因为它会占用您应用中的所有内存:
var Player = function(){this.__gold = 0};
Player.prototype = {
get gold(){
return this.__gold * 2;
},
set gold(gold){
this.__gold = gold;
},
};
var p = new Player();
p.gold = 2;
alert(p.gold); // 4
Run Code Online (Sandbox Code Playgroud)
如果您实例10000对象:
HBP*_*HBP 18
在他回答三分钟后,我得出了与Mikhail Kraynov相同的结论.每次调用构造函数时,该解决方案都会定义新属性.我想知道,如你所说,是否有一种方法可以将吸气剂和制定者放入原型中.这是我想出的:
var User = (function () {
function User (id, nam) {
Object.defineProperty (this, '__', // Define property for field values
{ value: {} });
this.id = id;
this.nam = nam;
}
(function define_fields (fields){
fields.forEach (function (field_name) {
Object.defineProperty (User.prototype, field_name, {
get: function () { return this.__ [field_name]; },
set: function (new_value) {
// some business logic goes here
this.__[field_name] = new_value;
}
});
});
}) (fields);
return User;
}) ();
Run Code Online (Sandbox Code Playgroud)
在这个解决方案中,我在原型中定义字段getter和setter,但在每个保存字段值的实例中引用(隐藏)属性.
请看这里的小提琴:http://jsfiddle.net/Ca7yq
我在小提琴中添加了一些代码,以显示对枚举属性的一些影响:http://jsfiddle.net/Ca7yq/1/
在我看来,当您为原型定义属性时,所有实例都共享该属性.所以正确的变体可能是
var User = (function(){
// constructor
function User(id, name){
this.id = id
this.name = name
Object.defineProperty(this, "name", {
get: function(){ return name },
set: function(new_value){
//Some business logic, upperCase, for example
new_value = new_value.toUpperCase();
name = new_value
}
})
}
return User;
})();
Run Code Online (Sandbox Code Playgroud)
在所有用户实例的原型对象上定义属性时,所有这些对象将共享相同的value变量。如果那不是您想要的,则需要defineFields分别在构造函数中分别调用每个用户实例:
function User(id, name){
this.define_fields(["name", "id"]);
this.id = id
this.name = name
}
User.prototype.define_fields = function(fields) {
var user = this;
fields.forEach(function(field_name) {
var value;
Object.defineProperty(user, field_name, {
get: function(){ return value; },
set: function(new_value){
/* some business logic goes here */
value = new_value;
}
});
});
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
25597 次 |
| 最近记录: |