new instance of object acting as reference?

巧了我就是萌 提交于 2019-12-12 00:21:42

问题


I am having a problem creating new instances of an object.

Using the below code I was expecting each element to have it's own random value (which is happening).

But then I was also expecting the this.element value to be contained to each instance of the object, but instead every time the value is changed in any instance of the object it is updating in all of them.

var Instance = function(element) {
    this.$element = $(element);
    this.subInstance.parent = this;
}

Instance.prototype = {

    subInstance: {

        parent: null,
        $element: null,

        init: function() {
            var $this = this;
            this.$element = this.parent.$element;

            //test for what this.$element refers to in init function
            var random = Math.random();
            $('.element', this.$element).text('Updated ' + random);

            //test for what this.$element refers to in an event handler
            $('.element', this.$element).on('click', function(e) {
                $this.$element.css('background-color', '#f00');
            });
        }
    }
}
$('div.instance').each(function(i, o) {
    var instance = new Instance(o);
    instance.subInstance.init();
});​

Now I know I could move subInstance out of the prototype and into the constructor using this.subInstance = {... but that seems wrong, why is this.$element not contained to each instance of the object?

JSFiddle of both examples: http://jsfiddle.net/q7zAg/


回答1:


It may seem wrong, but it's not. If each object created from the constructor needs to work with a unique subInstance, you'll need to create a new one for each individual instance. On the prototype it will be shared.

However, one thing you could do would be to use Object.create to create a new instance that inherits from the prototyped subInstance. Then you get the benefit of some reuse, and each instance can modify its own object.

var Instance = function(element) {
    this.$element = $(element);
    this.subInstance = Object.create(this.subInstance);
    this.subInstance.parent = this;
}

Now some may argue that the subInstance still shouldn't be on the prototype, but rather should be a local variable in an IIFE. I would tend to agree with this.

Here's an example:

var Instance = (function() {
    var _subInstance = {
        parent: null,
        $element: null,
        init: function() {
            // ...
        }
    };

    var Instance = function(element) {
        this.$element = $(element);
        this.subInstance = Object.create(_subInstance);
        this.subInstance.parent = this;
    };

       // other prototyped props
    Instance.prototype.foo = "bar";

    return Instance;
})();



回答2:


Note that a function's this is set by how the function is called, not how it's declared or initialised (other than using bind).

In your code you have:

> Instance.prototype = {
>     subInstance: {

which assigns an object to Instance.prototype that has a subInstance property that is an Object.

Then there is:

>         init: function() {
>             var $this = this;
>             this.$element = this.parent.$element;

The method is called as:

> instance.subInstance.init();

So this within the init method always references the same object (i.e. Instance.prototype.subInstance), so assignments to this.$element keep replacing the value.




回答3:


var Obj = 
{
    internal:null,

    __init:function(data){
        this.internal = data;
        return this
    },
    get:function(){
        return this.internal;
    },
    init:function(){
        var args = arguments,instance = function(){
             return this.__init.apply(this,args);
        };
        instance.prototype = this;
        return new instance();
    }
}

console.log(Obj.init(123).get());
console.log(Obj.get());
console.log(Obj.init(321).get());
console.log(Obj.get());


来源:https://stackoverflow.com/questions/13223618/new-instance-of-object-acting-as-reference

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!