8DK
8DK

Reputation: 714

Prototypes and object properties. Why do they act differently?

Why does the prototype differ from a normal object?

var obj={'length':4}

obj._length=obj.length

console.log(obj._length);   // 4

An array is an object and its prototype is too, so the same behavior should be seen...

var a=[0,1,2,3];


Array.prototype._length=Array.prototype.length;


console.log(a.length,a._length);    // 4,0

I am not going to use this in practice but, I do want to better understand what is going on here.

Edit: How would you see the same behavior?

Upvotes: 1

Views: 49

Answers (1)

thefourtheye
thefourtheye

Reputation: 239443

In your first case, you are creating a new property called _length on the object and assigning the length property's value in it. So, changing one will not affect the other. You can confirm it like this

var obj={'length':4}
obj._length=obj.length
console.log(obj._length);
# 4
obj.length = 15;
console.log(obj._length);
# 4

In your second case, when you create an Array object, the length property will be set on the object itself, whereas, _length is in the prototype chain, not on the object itself.

console.log(a.hasOwnProperty("length"), a.hasOwnProperty("_length"));
# true false

Also, you have created a variable in the Array's prototype with the name _length, with the default length 0 (console.log(Array.prototype.length);). So, all the subsequent arrays will have that property too.

var a = [0, 1, 2, 3];
Array.prototype._length = Array.prototype.length;
console.log([]._length);
# 0

So, we are talking about two different properties here. length is specific to all the Array objects, where as _length is common to all the Array objects.

You can confirm that like this

var a = [0, 1, 2, 3];
Array.prototype._length = Array.prototype.length;
console.log([1, 2, 3]._length);
# 0
console.log([1, 2, 3, 4]._length);
# 0

Since _length is not on themselves, when you try to access them, they look up the prototype chain to find one in Array.prototype. So, they both are printing 0.

If you want to get the length with the _length property, you can define it in the prototype, like this

Object.defineProperty(Array.prototype, "_length", {
    get: function() {
        return this.length;
    },
    set: function(newValue) {
        this.length = newValue;
    }
});

console.log([]._length);
# 0
console.log([1, 2, 3]._length);
# 3

Upvotes: 3

Related Questions