Does this example represent "Prototypal Inheritance"? - javascript

I have got an object literal (a), which I later use to make another object (b) add some properties, and again make an object with help of (b), ie (c) and add some properties to it.
Finally, I try access c.name which browser goes on for searching first in c, then b, then finally gets it from object a (same for second alert). But, I am a bit confused if this example correctly represents "Prototypal Inheritance"! (As, function constructure with prototype properties is not involved).
var a = {name: "Jenny", age: 27};
var b = Object.create(a);
b.state = "New York";
var c = Object.create(b);
c.flag = "50 star flag";
alert(c.name);
alert(b.age);

Yes, it does, the prototype chain you created is c -> b -> a.
var a = {};
var b = Object.create(a);
console.log(Object.getPrototypeOf(b) === a); // true
var c = Object.create(b);
console.log(Object.getPrototypeOf(c) === b); // true
If you're confused about missing constructor functions in this example, remember that Object.create is just a shortcut for
function Object.create(proto) {
function F() {}
F.prototype = proto;
return new F();
}
so the new and constructor are still executed under the hood. For the rationale behind Object.create see this classic article.

Related

Arrays contain value call by Reference so their pointer should turn same values and equate to true

As far as I know, the arrays and objects always act as pointers and just point to somewhere a memory location.
In the following example, as var a is updated, so as b pointing to same memory location as a, should also be updated and final answer should be true, true.
Why is it not happening??? At what instance of time, b gets a different pointer than a and why???
Example:
var a = [2,3,5];
var b = a;
a = [33,45];
console.log(a,b);
console.log(a==b,a===b);
However, to support my clause kindly look at following unchanged values example. Here I am sure both a and b point to same memory location containing data as [2,3,5]. They got same values and are always equated as true.
var a = [2,3,5];
var b = a;
console.log(a==b,a===b);
Because you are not updating the reference of the new object [33, 45].
Following code might help you understand better.
a = [{'a': 1}, {'b': 2}];
b = a;
console.log(a, b);
// creates new object and assigns to the same variable
b = b.concat ([{'c': 3}]);
console.log(a, b);
// but property of object is still referenced in by a and b
b[0].a = 100;
console.log(a,b);
a[2].c = 100; // throws exception, because 'a' does not have the reference to object which refers the object created in 'b'
console.log(a,b);
look at blow:
var a = [2,3,5];
var b = a;
and after the a = [33,45];
the pointer is point to a new obj, not the obj changed

javascript function this and prototype

The code is below:
function A() {
this.name = "kl";
this.obj2 = { a: 1 };
}
A.prototype.city = "china";
A.prototype.obj = {age: 30};
var a = new A();
var b = new A();
a.name = "kobe";
a.obj.age = 20;
a.city = "American"
a.obj2.a = 30;
console.log(b.name); // k1
console.log(b.city); // why china ?
console.log(b.obj); // when b.city = china, why b.obj = {age: 20}
console.log(b.obj2); // {a: 1}
My opinion is that a and b has its own this, so how you edit this[property] you can't change b its own this.value;
property declare so share property ? is right ?
but when obj is change will effect b.obj,
when city change will not effect b.city ?
Both objects have city and obj in their prototype chain. However, if you do a.city = "American" you are creating a new property city on a itself, shadowing the property city in the property chain.
Assigning to a property will (almost) always create that property on the object itself.
a.obj.age = 20; however reads (not assigns!) the object referenced by a.obj and updates its age property. a and b have the same prototype and thus a.obj and b.obj resolves to the same object. If the object is mutated in any way it will affect a and b in the same way.
Structure from the Chrome console:
Let's go through this line by line:
First of all, A.prototype points to an object.
When you run var a = new A();
You create a new object which is set to 'this'
This new object has properties name and obj2 which have values kl and { a: 1 }
this object is linked to the object A.prototype points to, thus a prototype chain is set up.
at the end of function A, the function actually runs return this;, which literally returns the object created to be assigned to a.
var b = new A(); does the same as above
when you run a.name = "kobe";, you're modifying the value from kl to kobe
when you run a.city = "American";, you're creating a new property city on a itself
and when you run a.obj2.a = 30;, you're also only modifying a value.
But when you run a.obj.age = 20;, something is different
a doesn't have the property obj on itself, so it goes up the prototype chain to the object A.prototype points to, and finds the property obj, so this line of code is actually modifying that obj, and changes the value of obj.age from 30 to 20.
when you execute b.name, since b has property name with value kl, so it prints kl
However, b doesn't have the property city on itself, so it goes up the prototype chain to the object A.prototype points to and see if it can find one, which it does, as previously you ran A.prototype.city = "china";, so it prints china.
When console.log(b.obj); is run, b goes up to the prototype chain and find obj on the object A.prototype points to, so it prints {age: 20}

Understanding pass by reference vs value with functions

As I understand objects are passed by reference in JavaScript (and primitives are passed by value?).
var a, b;
a = {
Foo: "Bar"
}
b = a;
a.Foo = "Other";
console.log(b.Foo); // "Other"
This worked similarly with arrays but did not work like I expect with functions:
var a, b;
a = function(){ return 20; }
b = a;
a = function(){ return 40; }
console.log(b()); // returns 20 ?
I'm confused because I thought functions are objects. Shouldn't the above example return 40?
In the first case, a.Foo = ..., You are changing the value of a property in the object, referred by both a and b. This is called mutating an object.
But in the second case, you are making a refer a new function object. Now, a and b are referring to different function objects.
That is why you are getting 20 in the second case.
First regarding the question in the title (which is actually different from what you demonstrate with the code examples):
"As I understand objects are passed by reference in JavaScript"
No, Javascript doesn't support passing parameter by reference at all. All parameters are passed by value, but the value can be a reference.
Example:
var a = { answer: 42 };
function f(x) {
alert(x.answer); // shows 42
x = { answer: 0 };
alert(x.answer); // shows 0
}
f(a);
alert(a.answer); // shows 42
As the parameter is passed by value, the variable x is separate from the variable a, so assigning a new object to x doesn't change the value of a.
Back to your code:
When you assign an object reference from a variable to another, it's the reference that is copied, not the object. You get two variables that reference the same object.
Either of the variables can be used to access members in the object, which your first code example demonstrates.
If you assign a new object to the first variable, you will replace the reference in the variable, you will not overwrite the object that it currently points to. The object is still intact, and the second variable still points to it. You get two variables that point to one object each, which your second code example demonstrates.
Further to #thefoutheye's answer, consider the following proof of your statement functions are objects:
var a, b;
a = function() { return 20; }
a.Foo = "Bar";
b = a;
a.Foo = "Other";
console.log(b.Foo); // "Other"
You are reassigning the variable a to a new function. That's not the same as changing a property value.
Try:
var a, b;
a = {Foo: function() {return 20;}};
b = a;
a.Foo = function() {return 40;};
console.log(b()); // returns 40

Why and how __proto__ remembers old properties of the constructor function's undefined prototype member?

Quick Note: Please don't explain basics of javascript inheritance in your answer.
Here is simple constructor function with some properties attached to it's prototype member.
function Foo() {
this.relationship = "Love";
};
Foo.prototype.name = "Natalie";
Foo.prototype.age = 22;
Foo.prototype.country = "France";
Now we create new object with Foo and test some basics. Everything is cool.
var girl = new Foo();
girl.hasOwnProperty("relationship"); //=> true
girl.hasOwnProperty("name"); //=> false
girl.relationship; //=> "Love"
girl.name; //=> "Natalie", this comes from Foo.prototype
girl.__proto__ === Foo.prototype; //=> true
girl.__proto__.name === Foo.prototype.name; //=> true
girl.name === Foo.prototype.name; //=> true
And if we update the value of Foo.prototype.name property, girl.name points to new value as it should.
Foo.prototype.name = "Lucia";
girl.name; //=> "Lucia", this comes from Foo.prototype
Mysterious thing happens when we change Foo.prototype and make it null, undefined, empty object etc.
Foo.prototype = null;
If our girl object had a hidden __ proto__ (ECMA [[Prototype]]) link to Foo.prototype, then after making Foo.prototype null there should be no chance for girl to get name property, but it does!
girl.name; //=> "Lucia"
girl.age; //=> 22
girl.country; //=> "France"
Now if we create another object with Foo at this point. It doesn't have name, age and country, because, of course, Foo.prototype is null.
var new_girl = new Foo();
new_girl.name; //=> undefined
new_girl.age; //=> undefined
new_girl.country; //=> undefined
So my question is how on earth previous object (girl) and his hidden __ proto__ link can remember those properties after we assigned Foo.prototype to null?
It's not mysterious at all, and it has nothing to do with inheritance.
It has to do with object-pointers/references.
var a = { name : "Bob", age : 32 };
var b = a;
b.name; // "Bob";
a.name = "Jim";
b.name; // "Jim";
a = null;
b.name; // "Jim";
What happened?
a and b were given pointers to the same object.
As you changed the properties of the object, by referencing one or the other (it doesn't matter if you change them on a or on b), the other reference will see the changes, too.
You aren't making new objects which have the same properties and values, you're just giving them both the address of the same object, and they're looking up the properties every time you ask them.
Then you reassign a.
You're not changing the object, you're giving a an address to some other place.
b still has the address.
So now think of it this way:
function Foo () { }
Foo.prototype = { name : "Bob", age : 32 };
var a = new Foo();
var b = new Foo();
a.__proto__ === Foo.prototype;
b.__proto__ === Foo.prototype;
Foo.prototype.age = 35;
a.age; // 35
b.age; // 35
// now we're replacing the `.prototype` reference with a brand new object
Foo.prototype = { name : "Sally", age : 16 };
a.__proto__ !== Foo.prototype;
b.__proto__ !== Foo.prototype;
a.name; // "Bob"
b.age; // 35
All the constructor is doing in the background is saying:
this.constructor = arguments.callee;
this.__proto__ = this.constructor.prototype;
So when you change properties on the object referenced by both this.constructor.prototype and this.__proto__ lookups on either will find the new values.
But removing a reference from one won't delete the object for the other.
If that's the result you want, then you'd need to erase each property of the prototype (doesn't matter where you do it from -- from the function or from any of the instances) and then nullify the .prototype by setting it to an empty object (null would cause errors on lesser browsers), so future objects have no access.

How to disable pointers usage in JS?

Why is the result {"a":"b","c":1}?
var foo = {"a":"b","c":0};
var bar = foo;
bar.c++;
alert(JSON.stringify(foo));
How to disable this behavior?
Both foo and bar variables reference the same object. It doesn't matter which reference you use to modify that object.
You cannot disable that behaviour, this is how JavaScript and many other major languages work. All you can do is to clone the object explicitly.
var foo = {"a":"b","c":0};
var bar = {"a":foo.a, "c": foo.c};
bar.c++;
What you're doing is making a second reference to an object but what it seems you want is a copy of that object instead.
If you want that functionality then you really want a copy function that copies all of the properties, one by one, into a new object:
// Take all the properties of 'obj' and copy them to a new object,
// then return that object
function copy(obj) {
var a = {};
for (var x in obj) a[x] = obj[x];
return a;
}
var foo = {"a":"b","c":0};
var bar = copy(foo);
bar.c++;
alert(JSON.stringify(foo));
and you'll get {"a":"b","c":0}
First, Javascript doesn't pass pointers, it passes references, slightly different. Secondly, there's no way to modify Javascript's default behavior, unfortunately fortunately.
What you might want to do is create a constructor and use that to create two similar, but separate instances of an object.
function Foo(a, b) {
this.a = a;
this.b = b;
}
var bar1 = new Foo(0, 0);
var bar2 = new Foo(0, 0);
bar2.b++;
console.log(bar1);
console.log(bar2);
>> {a:0, b:0};
>> {a:0, b:1};
You can't disable the way javascript works.
If you change a reference object, it effects all the object references...

Categories

Resources