Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
308 views
in Technique[技术] by (71.8m points)

javascript - JS defineProperty and prototype

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().

Here is an example code:

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

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

After running define_fields() I have my fields in the instance of the User

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

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: 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
            }
        })
    })
};
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Please don't implement any other version because it will eat all your memory in your app:

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

If 10000 objects are instantiated:

  • With my method: you will only have 2 functions in the memory;
  • With the other methods: 10000 * 2 = 20000 functions in the memory;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...