Javascript static elements

I've been using this for a while as a very good workaround for declaring static members for my objects, but I don't really understand why they become static, so I need someone to explain the following behavior to me.

I have the following declarations:

// Primitive so nothing interesting here
Array.prototype.someMember = "My value is not static";
// Object containing a primitive, now this is the deal
Array.prototype.someOtherMember = {
    value: "My value is static"
};

Array.prototype.changeMember = function (newValue) {
    // Change the primitive value
    this.someMember = newValue;
    // Change the primitive value inside the object
    this.someOtherMember.value = newValue;
};

      

And if tested like this:

var arr1 = [], arr2 = [], arr3 = [];
arr1.changeMember('I changed');
alert(arr1.someMember + ', ' + arr2.someMember + ', ' + arr3.someMember);
alert(arr1.someOtherMember.value + ', ' + arr2.someOtherMember.value + ', ' + arr3.someOtherMember.value);

      

Result:

I changed, My value is not static, My value is not static

I have changed, I have changed, I have changed

Now if I reassign the whole object in the method changeMember

like this:

Array.prototype.changeMember = function (newValue) {
    // Change the primitive value
    this.someMember = newValue;
    // Change the object
    this.someOtherMember = { value: newValue };
};

      

Then it is someOtherMember

no longer static, but instead the first instance of the array gets its own. I do not understand this behavior because in both cases I am accessing someOtherMember

via this

, so I cannot understand why it is static in the first case and not static in the second.

0


source to share


4 answers


There is no such thing in JS as a static property. What you see is the usual prototypal inheritance behavior. The key concept is this: Arrays and even all objects are sparse. An instance has no property unless it is explicitly assigned to that instance. until that happens, the prototype contains all the properties:

First case
Why do you see I changed, My value is not static, My value is not static

? Simple: when instantiating arrays, all instances will have a property called someMember

, but it actually doesn't. When you try to access anArray.someMember

, JS will first scan an instance for that property, if this instance doesn't have this property, JS will go to the prototype and look there someMember

. In your snippet, the method is changeMember

using this

to refer to the instance that is calling the method, not Object.getPrototypeOf(this).someMember

. The latter is a way to change a property at the prototype level. Shortly speaking:

arr1.changeMember('I changed');
// is the same as doing:
arr1.someMember = 'I changed';
arr1.someOtherMember.value = 'I changed';

      

An assignment someMember

is a simple assignment that sets an instance property.

Second case
The second assignment is to reassign a property of the referenced object Array.prototype.someOtherMember

. The object literal reference is not changed, only the object itself. As in any other language: when working with references, the object can change as it likes, the reference will remain the same (its value may change, but its memory address will not be).
When you override a method changeMember

to reassign a new Object literal for a property, you essentially create the same situation as in case one: directly assigning a new object to a property, which causes JS not to scan the prototype, but just assign the property at the instance level. You can use Object.getPrototypeOf(this)

or (for older browsers) this.prototype

:



Array.prototype.changeMember = function (val)
{
    this.someMember = 'I changed At instance level';
    Object.getPrototypeOf(this).someMember = 'Reassing prototype property to '+ val;
    Object.getPrototypeOf(this).someOtherMember = {value:val};//changes proto only
};

      

Having said that, if you want something like a static property, you are better off using Object.defineProperty

:

Object.defineProperty(Array.prototype,'sortofStatic',{value:'I cannot be changed',writable:false,configurable:false});

      

More examples of this can be found on MDN

+2


source


In someOtherMember, one object instance is shared between all the array instances.

In the first case, you change the value of that object, so the value changes for all instances of the array.



In the second case, you change the object itself. So the array instance will contain another object that the rest.

0


source


The first case is well understood.

Second case (where is someOtherMember

not a static member), you overwrite someOtherMember

every time you call changeMember

(remove a static member value

), so the static member ceases to exist.

0


source


Array.prototype.someMember = "My value is not static";

// Here `someOtherMember` is simply a property which points to a memory location
// So initially it will point to the same memory location for all instances of `Array`
Array.prototype.someOtherMember = {
    value: "My value is static"
};

Array.prototype.changeMember = function (newValue) {

    this.someMember = newValue;

    // Here we change a value stored in the memory location pointed by `someOtherMember`
    // As all instances point to the same memory location this change will reflect in all instances
    this.someOtherMember.value = newValue;
};


Array.prototype.changeMember = function (newValue) {

    this.someMember = newValue;

    // Here for this particular instance we make `someOtherMember` point to a new memory location.
    // All instances will point to the old memory location until `changeMember` is invoked.
    this.someOtherMember = { value: newValue };
};

      

0


source







All Articles