How many times parent object gets created during prototypal inheritance - javascript

I have read a lot on how prototypal inheritance works and how the interpreter travels the prototype chain to find the property.
function Man()
{
this.hands=2;//1
}
function father()
{
this.name="";
}
father.prototype= new Man();//2
var malay= new father();
var abhik= new father();
Now my question is that statement #1 & #2 is only invoked once . So "abhik" and "malay" should both share the same Man object ?
So there will be 3 objects in memory .
1.abhik
2.malay
3.man (One instance shared by both)
So by that logic the changed value should be shared across objects ?
malay.hands=3;
console.log(abhik.hands);
abhik.hands=4;
console.log(malay.hands);
But it is not the case.
Why so ?

Your understanding is correct that there are 3 objects and both abhik and malay inherit from the same Man instance. But when you set new hands properties on the malay and abhik objects, you give them their own hands property and they are no longer inheriting the hands property from the prototype Man.
Illustration:
After you first create malay and abhik, here is a mock of your three objects:
father.prototype -> {hands: 2}
malay -> {name: ""} // Empty name property, NO hands property
abhik -> {name: ""} // Empty name property, NO hands property
When you check for the hands property on malay or abhik, the interpreter will see that there is no such property and will check up the prototype chain and will find that their parent father.prototype does have a hands property, so the interpreter will report that value, which is 2.
After you set the hands properties, your objects look like this:
father.prototype -> {hands: 2}
malay -> {name: "", hands: 3} // Empty name property, OWN hands property
abhik -> {name: "", hands: 4} // Empty name property, OWN hands property
Now your objects all have their own hands properties.
Resource: Here is a very well-written (but long) article about javascript inheritance:
http://manuel.kiessling.net/2012/03/23/object-orientation-and-inheritance-in-javascript-a-comprehensive-explanation/

If you need to share a primitive type or immutable among instances you can use closures to retain it's value and use getters and setters to access it.
function Man()
{
var hands=2;
return {
getHands:function(){
return hands;
},
setHands:function(number){
hands=number;
}
}
}
function Father(name)
{
this.name=name;
}
Father.prototype= Man();
malay=new Father("malay");
abhik=new Father("abhik");
malay.setHands(4);
console.log(abhik.getHands());
console.log(malay.getHands());
If you need Father to be an instance of Man you can do the following:
function Hands(){
var hands=2;
return {
get:function(){
return hands;
},
set:function(number){
hands=number;
}
}
}
function Man(){
this.age=18;
this.array=[];
}
Man.prototype.hands=Hands();
function Father(name){
//take ownership (copy) of every variable
//defined in the Man function body
//with this.... prototype defined
//are still shared among instances
Man.call(this);
this.name=name;
}
Father.prototype= new Man();
malay=new Father("malay");
abhik=new Father("abhik");
malay.hands.set(4);
console.log(abhik.hands.get());
console.log(malay.hands.get());
malay.age=34;
console.log(abhik.age);//from Man.age
console.log(malay.age);//from malay.age
delete malay.age;
console.log(malay.age);//from Man.age
malay.array.push(22);
console.log(abhik.array);// is [] but would be [22]
// if Man.call(this) was not in the Father function
console.log(malay instanceof Man);

Related

Object creation and use of the prototype delegation

In the following example i have a simple Spy object. I wanted to create another object setting the prototype with the original object, so I've used Object.create().
Now I have a new object, which have just some properties from the original ('code' and 'breath' method). All the other properties (objects - 'name' and arrays - 'enemies') are in the _proto_ object, which i can use, because they are delegated to the original object. So far so good.
The tricky part is that if I change anything in the AnotherSpy included in the _proto_ object (the object name for example), those changes will be reflected in all the objects created from the original spy, including himself!
I also tried create a new object with using JSON.parse(), but in this way I have a new object which only have access to the 2 things that were previously in the _proto_ object - the array of enemies and the name object, without being able to use any methods of the original object (the 'breath' method).
let Spy = {
code: '007',
enemies: ['Dr.No'],
fullName: {
firstName: 'James',
lastName: 'Bond'
},
breath: function() {
console.log('im breathing..')
}
}
// original Spy breathing
Spy.breath(); // ok, he breaths
// create a new object with Object.create()
let OtherSpy = Object.create(Spy);
console.log(OtherSpy) // have direct access to properties 'code' and function 'breath' and all the others throught the __proto__ object
// Make OtherSpy breath
OtherSpy.breath(); // ok, he is breathing
// so far so good. Lets change the property and function on the OtherSpy
OtherSpy.code = '008';
OtherSpy.breath = () => {
console.log('im a new breathing')
};
OtherSpy.breath(); // ok, he's breathing differently
console.log(Spy.code); // 007 ok, original spy has the same code
Spy.breath() // ok, he stills breath in the same way.
// change the object 'name' of the OtherSpy
OtherSpy.fullName.firstName = 'Enemy';
// That change will reflect also on the original Spy...
console.log(Spy.fullName.firstName); // Enemy !!!!
// Trying in another way:
let NewSpy = JSON.parse(JSON.stringify(Spy));
console.log('NewSpy')
console.log(NewSpy) // now i dont have access to methods in the original object
NewSpy.breath() // Uncaught TypeError: NewSpy.breath is not a function
It seems that all properties included in the _proto_ object are shared in all objects that use that prototype chain.
Aside from this tricky parts that would greatly appreciate an explanation, I would like to know the proper way to create an object in JavaScript (without using ES6 classes) in order to get the advantage of the prototype delegation
and to be able to modify the properties and functions of the derived object without messing up with the original object nor any other derived objects.
Thanks in advance!
Nested properties are somewhat unuseful, so you may flatten it through using getters/setters:
const Spy = {
firstName: "Agent",
lastName: "Unnamed",
breath(){
console.log(`${this.fullName} is breathing`);
},
get fullName(){
return this.firstName + " " + this.lastName;
},
set fullName(name){
const [first, last] = name.split(" ");
this.firstName = first;
this.lastName = last;
}
};
const james = Object.create(Spy);
james.fullName = "James Bond";
james.breath();
console.log(james.fullName, james.firstName, james.lastName);
Another way would be to construct the name object inside of an constructor:
function Spy(name, code, enemies){
this.name = (([first, last]) => ({first, last}))(name.split(" "));
this.name.toString = () => name;
this.code = code;
this.enemies = enemies;
}
Spy.prototype = {
breath(){
console.log(`${this.name} is breathing`);
}
}
Usable as:
const james = new Spy("James Bond", "007", ["Dr. No"]);
james.breath();
console.log(james.name, "" + james.name);

Javascript "new" keyword making references to "class" properties

I have a javascript "class", that I instanciate several times.
My issue is that modifying properties from the instances does actually modify those properties of the "class", so further instances are not initialized in the way I'd like.
Here is a simplified snippet of what happens, the original code is using BackboneJS but this is enough to illustrate my case:
var foo = function() {
this.defaults.id = 1;
};
// This is my property
foo.prototype.defaults = {
id: 0,
};
console.log( foo.prototype.defaults ); // => {id: 0}
var bar = new foo();
console.log( foo.prototype.defaults ); // => {id: 1}
I thought that the "new" keyword would make a brand new object but it seems that it just makes a reference to the prototype properties.
The best option I came with is to clone all properties from inside the constructor...
Do anyone have a clean way to achieve a clean "Class Property" behavior ?
Many thanks in advance,
Romain.
Edit: It does not work from the SO snippet... just copy/paste it to your console if you want.
The prototype is shared among all objects of this type. A new copy is not made. The usual way to initialize properties that are to be unique to this instance is to initialize them directly in the constructor:
this.property = "foo";
This will override any property of the same name in the prototype and will be unique per instance.
In general, the prototype is not used for data properties because they are shared among all instances. If you want to initialize an object with a default set of data properties, the "best practice" for that is to assign a default set of properties into the object instance and then set any overrides. You can't just assign a default object because objects are assigned by pointer, not by copy so all objects would still be pointing at the same object (the same issue you have when using the prototype).
You could initialize your object with a set of defaults like this:
var foo = function() {
this.defaults = {};
// copy default properties
for (var prop in foo.defaults) {
this.defaults[prop] = foo.defaults[prop];
}
this.defaults.id = 1;
};
// defaults (not on the prototype)
foo.defaults = {
id: 0,
something: "whatever",
line: 22
};
Though, in practice, it is usually easier to just code in the defaults like this:
var foo = function() {
this.options = {
id: 1,
something: "whatever",
line: 22
};
};

Js Prototype simple types and objects

Is prototype inheritance behaving differently based on the type? Is the contextual reference THIS working different in these two cases? Why in this examples, one is accessing to the prototype and the other one is creating a new property to the object?
var Player = function(){};
Player.prototype.name = '';
Player.prototype.set_name = function(name){this.name = name;}
var p1 = new Player();
var p2 = new Player();
p1.set_name('Johanna');
Value return by these two:
// Checking object properties
>p1
Player {name: "Johanna", set_name: function}
>p2
Player {name: "", set_name: function}
// Checking prototypes
>p1.__proto__
Object {name: "", set_name: function}
>p2.__proto__
Object {name: "", set_name: function}
But if I do the Player with name as an object property, the function set_name is modifying the prototype.
var Player = function(){};
Player.prototype.name = {};
Player.prototype.set_name = function(name){this.name['first_name'] = name;}
var p1 = new Player();
var p2 = new Player();
p1.set_name('Andrew');
Value return by these two:
// Checking object properties
>p1.name
Object {first_name: "Andrew"}
>p2.name
Object {first_name: "Andrew"}
// Checking prototypes
>p1.__proto__.name
Object {first_name: "Andrew"}
>p2.__proto__.name
Object {first_name: "Andrew"}
Why is this happening? What concept(s) am I missing?
Inheritance chain
When you create an object with a constructor function, the inheritance chain goes like this, for lookup.
The current object will be searched.
Prototype of the parent will be searched.
Prototype of the parent's parent will be searched.
...
And finally the global object will be searched. If it is not found anywhere, undefined will be returned. If the value being looked up is found in any of these levels, it will be returned immediately.
Note: Assignments won't go up the inheritance chain. If you assign a value to an attribute of an object (if it is not present it will be created) then the value will be assigned to that attribute.
First case:
You are doing
this.name = name;
So,
p1.set_name('Andrew');
creates a new name attribute in p1 and stores Andrew in it. And when you tried to print p1, the name was looked up on p1 and it was found in p1 itself. So, Andrew was returned. But, when you printed p2, name is not found in p2. It goes up in the hierarchy and finds the name in parent's prototype. So, it returns the empty string.
Second case:
You are doing
this.name['first_name'] = name;
So,
p1.set_name('Andrew');
looks up name in p1. Because you are trying to access 'first_name' on this.name. So, it tries to retrieve name attribute. It doesn't find it in p1, so goes up and finds it in the parent's prototype. It is an empty object and name gets assigned to first_name attribute of that object.
We know that p2's prototype is the same as p1's prototype. We can confirm that like this
console.log(p1.__proto__ === p2.__proto__);
# true
So, when you look up p2's prototype, which is the same as p1's prototype, the name Andrew is found.
As a general case variables and such are set in the constructor.
For more info on the subject and a better explanation than i can do reference here: http://javascriptweblog.wordpress.com/2010/06/07/understanding-javascript-prototypes/
// Constructor
function Player() {
this.names = '';
};
// Public Method
Player.prototype.set_name = function(name){
this.name = name;
}
// Static method
Player.walk = function() {}
var player1 = new Player();
player1.set_name('John Doe'); // fires the public method
Player.walk(); // fires the static method

why prototype is undefined

I known this has been asked hundreds of times, however, I can't seem to grasp the concept of prototype
Here's my sample script
var config = {
writable: true,
enumerable: true,
configurable: true
};
var defineProperty = function(obj, name, value) {
config.value = value;
Object.defineProperty(obj, name, config);
}
var man= Object.create(null);
defineProperty(man, 'sex', "male");
var person = Object.create(man);
person.greet = function (person) {
return this.name + ': Why, hello there, ' + person + '.'
}
var p=Object.getPrototypeOf(person);
alert(p.sex);//shows male
person.prototype.age=13;//why there is a error said the prototype is undefined? I thought it supposed be man object...
var child=function(){}
child.prototype.color="red";//why this line doesn't show error? both child and person are an object .
alert(child.prototype.color);//shows red
var ch=Object.getPrototypeOf(child);
alert(ch.color);//why it is undefined? it is supposed red.
Hope you can give me some helps... thanks.
Updated:
Thanks your guys kindly help, Based on Elclanrs's answer, Below is what I learned.
Function is the one of the build-in objects in javascript. the 3 format creation function object are equal.
var function_name = new Function(arg1, arg2, ..., argN, function_body)
function function_name(arg1, arg2, ..., argN)
{
...
}
var function_name=function(arg1, arg2, ..., argN)
{
...
}
So, that is why create a prototype chain we have to create a function and then call it with the new keyword .
Function.prototype is the reference to All the Function object prototype.
Cheers
The prototype property only exists on functions, and person is not a function. It's an object.
Here's what's happening:
var man = Object.create(null); // man (object) -> null
man.sex = "male";
var person = Object.create(man); // person (object) -> man (object) -> null
person.greet = function () { ... };
var p = Object.getPrototypeOf(person); // man (object) -> null
alert(p.sex); // p is the same object as man
person.prototype.age = 13; // person doesn't have a prototype
var child = function () {}; // child (function) -> Function.prototype
// -> Object.prototype -> null
child.prototype.color = "red"; // child has a prototype
var ch = Object.getPrototypeOf(child); // Function.prototype
alert(ch.color); // ch is not the same as color.prototype
// ch is Function.prototype
For more information I suggest you read this answer: https://stackoverflow.com/a/8096017/783743
Edit: To explain what's happening in as few words as possible:
Everything in JavaScript is an object except primitive values (booleans, numbers and strings), and null and undefined.
All objects have a property called [[proto]] which is not accessible to the programmer. However most engines make this property accessible as __proto__.
When you create an object like var o = { a: false, b: "something", ... } then o.__proto__ is Object.prototype.
When you create an object like var o = Object.create(something) then o.__proto__ is something.
When you create an object like var o = new f(a, b, ...) then o.__proto__ is f.prototype.
When JavaScript can't find a property on o it searches for the property on o.__proto__ and then o.__proto__.__proto__ etc until it either finds the property or the proto chain ends in null (in which case the property is undefined).
Finally, Object.getPrototypeOf(o) returns o.__proto__ and not o.prototype - __proto__ exists on all objects including functions but prototype only exists on functions.
I think you might be mixing concepts. Try grasping the concept of prototypes with classic prototype inheritance first, then you can get into all the new Object stuff.
In JavaScript, every object (numbers, strings, objects, functions, arrays, regex, dates...) has a prototype which you can think of as a collection of methods (functions) that are common to all current and future instances of that object.
To create a prototype chain you have to create a function and then call it with the new keyword to specify that it is a constructor. You can think of constructors as the main function that takes the parameters necessary to build new instances of your object.
Having this in mind, you can extend native objects or create your own new prototype chains. This is similar to the concept of classes but much more powerful in practice.
Similar to your example, you could write a prototype chain like this:
// Very basic helper to extend prototypes of objects
// I'm attaching this method to the Function prototype
// so it'll be available for every function
Function.prototype.inherits = function(parent) {
this.prototype = Object.create(parent.prototype);
}
// Person constructor
function Person(name, age, sex) {
// Common to all Persons
this.name = name;
this.age = age;
this.sex = sex;
}
Person.prototype = {
// common to all Persons
say: function(words) {
return this.name +'says: '+ words;
}
};
// Student constructor
function Student(name, age, sex, school) {
// Set the variables on the parent object Person
// using Student as a context.
// This is similar to what other laguanges call 'super'
Person.call(this, name, age, sex);
this.school = school; // unique to Student
}
Student.inherits(Person); // inherit the prototype of Person
var mike = new Student('Mike', 25, 'male', 'Downtown'); // create new student
console.log(mike.say('hello world')); //=> "Mike says: hello world"
In newer version of JavaScript (read EcmaScript) they added new ways to deal with objects and extend them. But the concept it's a bit different from classical prototype inheritance, it seems more complicated, and some more knowledge of how JS works underneath would help to really understand how it works, plus it doesn't work in older browsers. That's why I suggest you start with the classical pattern for which you'll find accurate and abundant information on the internet.

My dilemma involving JavaScript's Prototypal Inheritance and the hasOwnProperty method

Basically everyone writing about member enumeration in JavaScript heavily advocates the use of the hasOwnProperty method as to avoid going up the prototype-chain.
I understand that this is a form of defensive programming as to prevent iterating over members that are added, for example, to the Object.prototype. But what about the other inherited members? Say, members that are very close in the prototype chain...members that you actually Want to be enumerated over.
Let's say I have the following:
var beget = function (o) { // http://javascript.crockford.com/prototypal.html
function F() {};
F.prototype = o;
return new F();
};
var john = { name: 'john', surname: 'grech' },
mary = beget(john),
p;
mary.age = 42; //augmenting 'mary'
// 'surname' in mary => true
// mary.hasOwnProperty('surname') => false
for (p in mary) {
//skipping over non-direct members, meaning that we also skip members
//inherited from 'john'
if (!mary.hasOwnProperty(p)) {
continue;
}
console.log(p);
}
In the above sample, only age will be displayed, since age is the only direct-member of mary...the other two members, name and surname, are up the prototype chain.
But obviously, I want all the 3 members to be iterated over in the for..in construct; but if you remove the hasOwnProperty, you can then get members from Object.Prototype if someone adds functions to it.
So this is my dilemma.
Do you use prototypal inheritance in combination with the hasOwnProperty method but risk getting members that are too far up the chain during enumeration?
Or do you use the other forms of inheritance that add members directly to the object rather than the prototype?
Hm. You are saying " very close in the prototype chain", but actually, what does it mean very close? Is the three level deep "close" or "far".
Anyway, you could change a bit beget function and implement own hasOwnProperty function for every object, which would go through the prototype chain only till the Object level. This will solve your dilemma of getting members which are added to the Object.prototype by not using hasOwnProperty. Code attached bellow:
var beget = function (o) { // http://javascript.crockford.com/prototypal.html
function F() {
this.hasOwnProperty = function(key) {
return (key != "hasOwnProperty"
&& Object.prototype.hasOwnProperty.call( this, key )
|| o.hasOwnProperty( key )
);
}
};
F.prototype = o;
return new F();
};
var john = { name: 'john', surname: 'grech' },
mary = beget( john ),
p = beget( mary );
mary.age = 42; //augmenting 'mary'
mary.name = "mary";
p.size = "38";
// testing prototype of Object.
Object.prototype.not_own = function(){}
for(var i in p) {
console.debug('Key',i, p.hasOwnProperty(i));
}
// p.hasOwnProperty("size"); // -> true
// p.hasOwnProperty("age"); // -> true
// p.hasOwnProperty("name"); // -> true
// p.hasOwnProperty("not_own"); // -> false
If you need to iterate over the prototypal chain of an object you can use hasOwnProperty to skip direct members (as you said). This will of course also iterate through whichever other member that was added to the prototype of that object (Object.Prototype etc..). There's no way to avoid this.
It's like asking how to avoid enumerating over certain members of a car = {yellow, green, black} object (pseudocode)... you don't... you simply skip certain members based on their value.
Adding members directly to an object isn't really a form of inheritance, unless of course you create objects using the begetObject() technique... because it uses the Prototype to add members.

Categories