JS defineProperty和原型 [英] JS defineProperty and prototype

查看:200
本文介绍了JS defineProperty和原型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如您所知,我们可以使用 defineProperty()在JS中定义getter和setter。当我尝试使用 defineProperty()来扩展我的课时,我一直被困住。

As you know we can define getters and setters in JS using defineProperty(). I've been stuck when trying to extend my class using defineProperty().

这是一个示例代码:

我有一个必须添加到对象的字段数组

I have an array of fields which must be added to a object

fields = ["id", "name", "last_login"]

此外我还有将被修改的类

Also I have a class which will be modified

var User = (function(){
    // constructor
    function User(id, name){
        this.id     = id
        this.name   = name
    }
    return User;
})();

一个函数,它将使用 defineProperty()<为类添加字段/ code>

And a function which will add fields to the class using 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
            }
        })
    })
};

运行 define_fields()我有我的用户实例中的字段

define_fields(fields);
user1 = new User(1, "Thomas")
user2 = new User(2, "John")

但这些属性的值是相同的

But the values ​​of these properties are identical

console.log(user2.id, user2.name) // 2, John
console.log(user1.id, user1.name) // 2, John

有没有办法让 defineProperty()在这种情况下正常工作?
如果我理解问题是,对于每个类的实例,
变得相同,但我无法实现如何解决它。提前感谢
获取答案。

Is there any way to make defineProperty() work properly in this case? If I understand the problem is with value which becomes identical for each instance of the class but i can't realise how to fix it. Thanks in advance for your answers.

UPD:
这样会抛出RangeError:超出最大调用堆栈大小

UPD: This way throws "RangeError: Maximum call stack size exceeded"

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
            }
        })
    })
};


推荐答案

我得出了与Mikhail Kraynov 。每次调用构造函数时,该解决方案都会定义新属性。我想知道,如你所说,是否有一种方法可以将吸气剂和制定者放入原型中。这是我想出的:

I came to the same conclusion as Mikhail Kraynov three minutes after he answered. That solution defines new properties each time the constructor is called. I wondered if, as you asked, there was a way of putting the getters and setters in the prototype. Here is what I came up with:

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;
}) ();  

在这个解决方案中,我在原型中定义了字段getter和setter,但引用了一个(隐藏)属性每个保存字段值的实例。

In this solution I define the field getters and setters in the prototype but reference a (hidden) property in each instance which holds the field values.

请参阅此处的小提琴: http://jsfiddle.net/Ca7yq

See the fiddle here : http://jsfiddle.net/Ca7yq

我为小提琴添加了一些代码,以显示对枚举属性的一些影响: http://jsfiddle.net/Ca7yq/1/

I added some more code to the fiddle to show some effects on enumeration of properties : http://jsfiddle.net/Ca7yq/1/

这篇关于JS defineProperty和原型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆