How can I build a constructor-like function? - javascript

When I read the CHAPTER 6 OBJECT-ORIENTED PROGRAMMING of Professional JavaScript for Web Developers, It shows a pattern for create object by constructor.
// implicit way
function Person(name) {
this.name = name;
}
var person1 = new Person('Greg')
person1 instanceof Person
To create a new instance of Person, use the new operator. Calling a constructor in this manner essentially causes the following four steps to be taken:
Create a new object.
Assign the this value of the constructor to the new object (so this points to the new object).
Execute the code inside the constructor (adds properties to the new object).
Return the new object.
That show the implicit way how an object instance be created.
And I want to follow it explicitly. Something like:
function Person(name) {
var o = Object.call(this) // step 1 and step 2
o.name = name // step 3
return o // step 4
}
var person1 = new Person('Greg')
person1 instanceof Person // false
In fact, It can't work as the constructor pattern. Why? And how can I modify my code to create a constructor with the explicit way?
https://javascript.info/constructor-new

Because Object.call(this) makes little sense, as that function does not care of its context and returns a plain object. Instead you can use:
Object.create(this.constructor.prototype)

The book quoted leaves out a seriously important detail of what new does:
1 Create a new object.
really means
1.1 Create a new object,
1.2 which has been prototyped on the constructor function's prototype property.
Hence the results of:
function Person(name) {
var o = Object.create( Person.prototype);
o.name = name // step 3
return o // step 4
}
var person1 = new Person('Greg')
console.log( person1 instanceof Person); // true
console.log( person1.constructor) // Person
Not that you would do this in real code, but for learning purposes it's an interesting demonstration.
The constructor property
Generally an object inherits its "constructor" property from its inheritance chain, searching backwards from the object's __proto property.
You could create a local own-property of an object called "constructor" which would then shadow the inherited value (and which would also be enumerable by default).
If you set the constructor property of a function's prototype property, its value changes without the property becoming enumerable in the process:
function F() {}
console.log (F.prototype.hasOwnProperty("constructor")); // true
let f = new F();
console.log( f.constructor.name); // F
F.prototype.constructor = Object;
let g = new F();
console.log( g.constructor.name); // Object
F.prototype.foo = "bar";
for( var prop in F.prototype) {
console.log( "F.prototype.%s = %s", prop, F.prototype[ prop]); // foo only
}

Related

What is the difference let o1.prototype = Object.create(o2.prototype) and o1.prototype = o2.prototype? [duplicate]

This question already has answers here:
Why wouldn't I use Child.prototype = Parent.Prototype rather than Child.prototype = new Parent(); for Javascript inheritance?
(3 answers)
Benefits of using `Object.create` for inheritance
(4 answers)
Closed 3 years ago.
So I'm trying to understand the difference between o1.prototype = Object.create(o2.prototype) and o1.prototype = o2.prototype.
According to the answer to this question, the former sets obj2.prototype to by the prototype for obj1.prototype, but I'm having a hard time grasping why you would want that (the prototype of a new prototype for example is just Object.prototype since the prototype IS an Object without further inheritance). Furthermore, it doesn't seem to quite work the way the answer to that question suggests all the time.
In the following code, for example:
function o1(){}
o1.prototype.test = "test";
function o2(){}
o2.prototype = Object.create(o1.prototype);
let instance1 = Object.create(o1);
console.log(o2.prototype.test, instance1.prototype.test);
both o2.prototype.test and instance1.prototype.test print "test". So it doesn't seem to matter weather you assign the o2 directly to Object.create(o1.prototype) or set the o2's prototype to Object.create(o1.prototype).
Also, if I'm understanding this correctly, according to the answer in the linked question, if o1 is empty (which is it in this case) then setting o2 = o1 would be the same as setting setting o2 = Object.create(o1) which would also be the same as
function o1(){};
function o2(){};
o2.prototype = o1.prototype;
Is there any significant difference between those three? Also, if o2.prototype = Object.create(o1.prototype) creates an empty object with o1.prototype's prototype as it's own prototype, if o1's prototype is not empty, then how do the members of o1's prototype get imported into o2's prototype?
If you directly assign Parent.prototype to a child's prototype, they'll both be pointing to the same object. So, if you add a method, which only applies to the child class, Parent objects will also have access to them because Parent.prototype === Child.prototype
Example:
function Animal() {};
Animal.prototype.Eat = function() {
console.log("Eating")
}
function Human() {};
Human.prototype = Animal.prototype; // both point to the same object
Human.prototype.Drive = function() {
console.log("Driving")
}
var animal = new Animal();
var human = new Human();
animal.Eat();
human.Eat();
animal.Drive(); // Animals shouldn't be driving
human.Drive();
console.log("animal instanceof Human: ", animal instanceof Human) // true
If you use Object.create(Animal.prototype) instead, it creates a new object with the [[Prototype]] (also, but deprecated, __proto__) set to Anima.prototype. So, if any methods are not found on Human.prototype, it will fall back to Animal.prototype (In this case Eat)
function Animal() {};
Animal.prototype.Eat = function() {
console.log("Eating")
}
function Human() {};
Human.prototype = Object.create(Animal.prototype)
Human.prototype.constructor = Human; // update the constrcutor
Human.prototype.Drive = function() {
console.log("Driving")
}
var animal = new Animal;
var human = new Human;
animal.Eat();
human.Eat();
human.Drive();
try {
// This will throw an error because Animal.prototype doesn't have a Drive method
animal.Drive();
} catch {
console.log("Animals can't drive")
}
console.log("animal instanceof Animal: ", animal instanceof Animal) // true
console.log("animal instanceof Human: ", animal instanceof Human) // false
console.log("human instanceof Animal: ", human instanceof Animal) // true
console.log("human instanceof Human: ", human instanceof Human) // true
console.log(animal.constructor)
console.log(human.constructor)
When you access, human.Eat(), first the method will looked up directly under the human object. If not found, this will be searched in its prototype which is Human.prototype.
Object.getPrototypeOf(human) === Human.prototype;
Since, Eat method is not found there, the method will be looked inside the prototype of Human.prototype which is Animal.prototype
Object.getPrototypeOf(Human.prototype) === Animal.prototype
The method is found here and it will be executed.
Let's say you want to use human.hasOwnProperty('eyes'). It goes through the similar chain as above. If hasOwnProperty is not found on human object, Human.prototype or Animal.prototype, it will check inside Object.prototpye because
Object.getPrototypeOf(Animal.prototype) === Object.prototype
Object.prototype has a method called hasOwnProperty and that will be executed

Are properties defined in constructor function own or inherited?

I am new to Javascript sorry if this sounds as an easy question.
If I have following constructor function:
function Person(x,y){
this.name = x;
this.surname = y;
}
I am curious whether properties name and surname are considered own properties of objects of type Person or inherited?
e.g.
var x = new Person("John", "Doe");
I did some tests using hasOwnProperty which suggest they are considered own properties rather than inherited, just wanted to verify.
Yes, they are own properties. When instantiating an object with new Person, an object will be created, your function Person will be called, and this inside Person refers to this new object. You're then explicitly directly setting properties on this object. In essence, no different than this:
function person(obj) {
obj.name = 'Foo';
obj.surname = 'Bar';
}
var o = {};
person(o);
o.name // Foo
The easiest way for you to check this is to just try it and see.
But yes, they are considered own properties. Inside the constructor function, this is a reference to the newly constructed object (when Person is called with new).
It's essentially the same thing as doing
var x = {};
x.name = 'foo'
console.log(x.hasOwnProperty('name')); // true
Compare that to a prototype property:
function Person(name) {
this.name = name;
}
Person.prototype.brain = 'meat-like';
var p = new Person('Bob');
console.log(p.name); // Bob
console.log(p.brain); // meat-like
console.log(p.hasOwnProperty('name')); // true
console.log(p.hasOwnProperty('brain')); // false

Inheritance with Object.create() method in javascript [duplicate]

Javascript 1.9.3 / ECMAScript 5 introduces Object.create, which Douglas Crockford amongst others has been advocating for a long time. How do I replace new in the code below with Object.create?
var UserA = function(nameParam) {
this.id = MY_GLOBAL.nextId();
this.name = nameParam;
}
UserA.prototype.sayHello = function() {
console.log('Hello '+ this.name);
}
var bob = new UserA('bob');
bob.sayHello();
(Assume MY_GLOBAL.nextId exists).
The best I can come up with is:
var userB = {
init: function(nameParam) {
this.id = MY_GLOBAL.nextId();
this.name = nameParam;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var bob = Object.create(userB);
bob.init('Bob');
bob.sayHello();
There doesn't seem to be any advantage, so I think I'm not getting it. I'm probably being too neo-classical. How should I use Object.create to create user 'bob'?
With only one level of inheritance, your example may not let you see the real benefits of Object.create.
This methods allows you to easily implement differential inheritance, where objects can directly inherit from other objects.
On your userB example, I don't think that your init method should be public or even exist, if you call again this method on an existing object instance, the id and name properties will change.
Object.create lets you initialize object properties using its second argument, e.g.:
var userB = {
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var bob = Object.create(userB, {
'id' : {
value: MY_GLOBAL.nextId(),
enumerable:true // writable:false, configurable(deletable):false by default
},
'name': {
value: 'Bob',
enumerable: true
}
});
As you can see, the properties can be initialized on the second argument of Object.create, with an object literal using a syntax similar to the used by the Object.defineProperties and Object.defineProperty methods.
It lets you set the property attributes (enumerable, writable, or configurable), which can be really useful.
There is really no advantage in using Object.create(...) over new object.
Those advocating this method generally state rather ambiguous advantages: "scalability", or "more natural to JavaScript" etc.
However, I have yet to see a concrete example that shows that Object.create has any advantages over using new. On the contrary there are known problems with it. Sam Elsamman describes what happens when there are nested objects and Object.create(...) is used:
var Animal = {
traits: {},
}
var lion = Object.create(Animal);
lion.traits.legs = 4;
var bird = Object.create(Animal);
bird.traits.legs = 2;
alert(lion.traits.legs) // shows 2!!!
This occurs because Object.create(...) advocates a practice where data is used to create new objects; here the Animal datum becomes part of the prototype of lion and bird, and causes problems as it is shared. When using new the prototypal inheritance is explicit:
function Animal() {
this.traits = {};
}
function Lion() { }
Lion.prototype = new Animal();
function Bird() { }
Bird.prototype = new Animal();
var lion = new Lion();
lion.traits.legs = 4;
var bird = new Bird();
bird.traits.legs = 2;
alert(lion.traits.legs) // now shows 4
Regarding, the optional property attributes that are passed into Object.create(...), these can be added using Object.defineProperties(...).
Object.create is not yet standard on several browsers, for example IE8, Opera v11.5, Konq 4.3 do not have it. You can use Douglas Crockford's version of Object.create for those browsers but this doesn't include the second 'initialisation object' parameter used in CMS's answer.
For cross browser code one way to get object initialisation in the meantime is to customise Crockford's Object.create. Here is one method:-
Object.build = function(o) {
var initArgs = Array.prototype.slice.call(arguments,1)
function F() {
if((typeof o.init === 'function') && initArgs.length) {
o.init.apply(this,initArgs)
}
}
F.prototype = o
return new F()
}
This maintains Crockford prototypal inheritance, and also checks for any init method in the object, then runs it with your parameter(s), like say new man('John','Smith'). Your code then becomes:-
MY_GLOBAL = {i: 1, nextId: function(){return this.i++}} // For example
var userB = {
init: function(nameParam) {
this.id = MY_GLOBAL.nextId();
this.name = nameParam;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var bob = Object.build(userB, 'Bob'); // Different from your code
bob.sayHello();
So bob inherits the sayHello method and now has own properties id=1 and name='Bob'. These properties are both writable and enumerable of course. This is also a much simpler way to initialise than for ECMA Object.create especially if you aren't concerned about the writable, enumerable and configurable attributes.
For initialisation without an init method the following Crockford mod could be used:-
Object.gen = function(o) {
var makeArgs = arguments
function F() {
var prop, i=1, arg, val
for(prop in o) {
if(!o.hasOwnProperty(prop)) continue
val = o[prop]
arg = makeArgs[i++]
if(typeof arg === 'undefined') break
this[prop] = arg
}
}
F.prototype = o
return new F()
}
This fills the userB own properties, in the order they are defined, using the Object.gen parameters from left to right after the userB parameter. It uses the for(prop in o) loop so, by ECMA standards, the order of property enumeration cannot be guaranteed the same as the order of property definition. However, several code examples tested on (4) major browsers show they are the same, provided the hasOwnProperty filter is used, and sometimes even if not.
MY_GLOBAL = {i: 1, nextId: function(){return this.i++}}; // For example
var userB = {
name: null,
id: null,
sayHello: function() {
console.log('Hello '+ this.name);
}
}
var bob = Object.gen(userB, 'Bob', MY_GLOBAL.nextId());
Somewhat simpler I would say than Object.build since userB does not need an init method. Also userB is not specifically a constructor but looks like a normal singleton object. So with this method you can construct and initialise from normal plain objects.
TL;DR:
new Computer() will invoke the constructor function Computer(){} for one time, while Object.create(Computer.prototype) won't.
All the advantages are based on this point.
Sidenote about performance: Constructor invoking like new Computer() is heavily optimized by the engine, so it may be even faster than Object.create.
You could make the init method return this, and then chain the calls together, like this:
var userB = {
init: function(nameParam) {
this.id = MY_GLOBAL.nextId();
this.name = nameParam;
return this;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var bob = Object.create(userB).init('Bob');
Another possible usage of Object.create is to clone immutable objects in a cheap and effective way.
var anObj = {
a: "test",
b: "jest"
};
var bObj = Object.create(anObj);
bObj.b = "gone"; // replace an existing (by masking prototype)
bObj.c = "brand"; // add a new to demonstrate it is actually a new obj
// now bObj is {a: test, b: gone, c: brand}
Notes: The above snippet creates a clone of an source object (aka not a reference, as in cObj = aObj). It benefits over the copy-properties method (see 1), in that it does not copy object member properties. Rather it creates another -destination- object with it's prototype set on the source object. Moreover when properties are modified on the dest object, they are created "on the fly", masking the prototype's (src's) properties.This constitutes a fast an effective way of cloning immutable objects.
The caveat here is that this applies to source objects that should not be modified after creation (immutable). If the source object is modified after creation, all the clone's unmasked properties will be modified, too.
Fiddle here(http://jsfiddle.net/y5b5q/1/) (needs Object.create capable browser).
I think the main point in question - is to understand difference between new and Object.create approaches. Accordingly to this answer and to this video new keyword does next things:
Creates new object.
Links new object to constructor function (prototype).
Makes this variable point to the new object.
Executes constructor function using the new object and implicit perform return this;
Assigns constructor function name to new object's property constructor.
Object.create performs only 1st and 2nd steps!!!
In code example provided in question it isn't big deal, but in next example it is:
var onlineUsers = [];
function SiteMember(name) {
this.name = name;
onlineUsers.push(name);
}
SiteMember.prototype.getName = function() {
return this.name;
}
function Guest(name) {
SiteMember.call(this, name);
}
Guest.prototype = new SiteMember();
var g = new Guest('James');
console.log(onlineUsers);
As side effect result will be:
[ undefined, 'James' ]
because of Guest.prototype = new SiteMember();
But we don't need to execute parent constructor method, we need only make method getName to be available in Guest.
Hence we have to use Object.create.
If replace Guest.prototype = new SiteMember();
to Guest.prototype = Object.create(SiteMember.prototype); result be:
[ 'James' ]
Sometimes you cannot create an object with NEW but are still able to invoke the CREATE method.
For example: if you want to define a Custom Element it must derive from HTMLElement.
proto = new HTMLElement //fail :(
proto = Object.create( HTMLElement.prototype ) //OK :)
document.registerElement( "custom-element", { prototype: proto } )
The advantage is that Object.create is typically slower than new on most browsers
In this jsperf example, in a Chromium, browser new is 30 times as fast as Object.create(obj) although both are pretty fast. This is all pretty strange because new does more things (like invoking a constructor) where Object.create should be just creating a new Object with the passed in object as a prototype (secret link in Crockford-speak)
Perhaps the browsers have not caught up in making Object.create more efficient (perhaps they are basing it on new under the covers ... even in native code)
Summary:
Object.create() is a Javascript function which takes 2 arguments and returns a new object.
The first argument is an object which will be the prototype of the newly created object
The second argument is an object which will be the properties of the newly created object
Example:
const proto = {
talk : () => console.log('hi')
}
const props = {
age: {
writable: true,
configurable: true,
value: 26
}
}
let Person = Object.create(proto, props)
console.log(Person.age);
Person.talk();
Practical applications:
The main advantage of creating an object in this manner is that the prototype can be explicitly defined. When using an object literal, or the new keyword you have no control over this (however, you can overwrite them of course).
If we want to have a prototype The new keyword invokes a constructor function. With Object.create() there is no need for invoking or even declaring a constructor function.
It can Basically be a helpful tool when you want create objects in a very dynamic manner. We can make an object factory function which creates objects with different prototypes depending on the arguments received.
You have to make a custom Object.create() function. One that addresses Crockfords concerns and also calls your init function.
This will work:
var userBPrototype = {
init: function(nameParam) {
this.name = nameParam;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
function UserB(name) {
function F() {};
F.prototype = userBPrototype;
var f = new F;
f.init(name);
return f;
}
var bob = UserB('bob');
bob.sayHello();
Here UserB is like Object.create, but adjusted for our needs.
If you want, you can also call:
var bob = new UserB('bob');
While Douglas Crockford used to be a zealous advocate of Object.create() and he is basically the reason why this construct actually is in javascript, he no longer has this opinion.
He stopped using Object.create, because he stopped using this keyword altogether as it causes too much trouble. For example, if you are not careful it can easily point to the global object, which can have really bad consequences. And he claims that without using this Object.create does not make sense anymore.
You can check this video from 2014 where he talks at Nordic.js:
https://www.youtube.com/watch?v=PSGEjv3Tqo0
new and Object.create serve different purposes. new is intended to create a new instance of an object type. Object.create is intended to simply create a new object and set its prototype. Why is this useful? To implement inheritance without accessing the __proto__ property. An object instance's prototype referred to as [[Prototype]] is an internal property of the virtual machine and is not intended to be directly accessed. The only reason it is actually possible to directly access [[Prototype]] as the __proto__ property is because it has always been a de-facto standard of every major virtual machine's implementation of ECMAScript, and at this point removing it would break a lot of existing code.
In response to the answer above by 7ochem, objects should absolutely never have their prototype set to the result of a new statement, not only because there's no point calling the same prototype constructor multiple times but also because two instances of the same class can end up with different behavior if one's prototype is modified after being created. Both examples are simply bad code as a result of misunderstanding and breaking the intended behavior of the prototype inheritance chain.
Instead of accessing __proto__, an instance's prototype should be written to when an it is created with Object.create or afterward with Object.setPrototypeOf, and read with Object.getPrototypeOf or Object.isPrototypeOf.
Also, as the Mozilla documentation of Object.setPrototypeOf points out, it is a bad idea to modify the prototype of an object after it is created for performance reasons, in addition to the fact that modifying an object's prototype after it is created can cause undefined behavior if a given piece of code that accesses it can be executed before OR after the prototype is modified, unless that code is very careful to check the current prototype or not access any property that differs between the two.
Given
const X = function (v) { this.v = v };
X.prototype.whatAmI = 'X';
X.prototype.getWhatIAm = () => this.whatAmI;
X.prototype.getV = () => this.v;
the following VM pseudo-code is equivalent to the statement const x0 = new X(1);:
const x0 = {};
x0.[[Prototype]] = X.prototype;
X.prototype.constructor.call(x0, 1);
Note although the constructor can return any value, the new statement always ignores its return value and returns a reference to the newly created object.
And the following pseudo-code is equivalent to the statement const x1 = Object.create(X.prototype);:
const x0 = {};
x0.[[Prototype]] = X.prototype;
As you can see, the only difference between the two is that Object.create does not execute the constructor, which can actually return any value but simply returns the new object reference this if not otherwise specified.
Now, if we wanted to create a subclass Y with the following definition:
const Y = function(u) { this.u = u; }
Y.prototype.whatAmI = 'Y';
Y.prototype.getU = () => this.u;
Then we can make it inherit from X like this by writing to __proto__:
Y.prototype.__proto__ = X.prototype;
While the same thing could be accomplished without ever writing to __proto__ with:
Y.prototype = Object.create(X.prototype);
Y.prototype.constructor = Y;
In the latter case, it is necessary to set the constructor property of the prototype so that the correct constructor is called by the new Y statement, otherwise new Y will call the function X. If the programmer does want new Y to call X, it would be more properly done in Y's constructor with X.call(this, u)
new Operator
This is used to create object from a constructor function
The new keywords also executes the constructor function
function Car() {
console.log(this) // this points to myCar
this.name = "Honda";
}
var myCar = new Car()
console.log(myCar) // Car {name: "Honda", constructor: Object}
console.log(myCar.name) // Honda
console.log(myCar instanceof Car) // true
console.log(myCar.constructor) // function Car() {}
console.log(myCar.constructor === Car) // true
console.log(typeof myCar) // object
Object.create
You can also use Object.create to create a new object
But, it does not execute the constructor function
Object.create is used to create an object from another object
const Car = {
name: "Honda"
}
var myCar = Object.create(Car)
console.log(myCar) // Object {}
console.log(myCar.name) // Honda
console.log(myCar instanceof Car) // ERROR
console.log(myCar.constructor) // Anonymous function object
console.log(myCar.constructor === Car) // false
console.log(typeof myCar) // object
I prefer a closure approach.
I still use new.
I don't use Object.create.
I don't use this.
I still use new as I like the declarative nature of it.
Consider this for simple inheritance.
window.Quad = (function() {
function Quad() {
const wheels = 4;
const drivingWheels = 2;
let motorSize = 0;
function setMotorSize(_) {
motorSize = _;
}
function getMotorSize() {
return motorSize;
}
function getWheelCount() {
return wheels;
}
function getDrivingWheelCount() {
return drivingWheels;
}
return Object.freeze({
getWheelCount,
getDrivingWheelCount,
getMotorSize,
setMotorSize
});
}
return Object.freeze(Quad);
})();
window.Car4wd = (function() {
function Car4wd() {
const quad = new Quad();
const spareWheels = 1;
const extraDrivingWheels = 2;
function getSpareWheelCount() {
return spareWheels;
}
function getDrivingWheelCount() {
return quad.getDrivingWheelCount() + extraDrivingWheels;
}
return Object.freeze(Object.assign({}, quad, {
getSpareWheelCount,
getDrivingWheelCount
}));
}
return Object.freeze(Car4wd);
})();
let myQuad = new Quad();
let myCar = new Car4wd();
console.log(myQuad.getWheelCount()); // 4
console.log(myQuad.getDrivingWheelCount()); // 2
console.log(myCar.getWheelCount()); // 4
console.log(myCar.getDrivingWheelCount()); // 4 - The overridden method is called
console.log(myCar.getSpareWheelCount()); // 1
Feedback encouraged.

Can you help clarify Javascript prototype inheritance method invocation?

In this block of code:
var Fruit = function() {}
Fruit.prototype = {
color: function () {
console.log('Fruit color...')
}
}
var Apple = function () {}
Apple.prototype = new Fruit()
Apple.prototype.constructor = Apple
var a = new Apple()
Apple.prototype = null // the question!!!
a.color()
When Apple.prototype has been set to null, why can the instance a still invoke the color method?
You're changing the Apple.prototype reference after you have created the instance a.
Changing the reference here doesn't change it for existing instances.
You'll also find
var a = new Apple();
Apple.prototype = {}; // some other object
a instanceof Apple; // false
i.e. because we've changed the inheritance chain of Apple a is no longer considered an Apple.
Setting Foo.prototype = null will cause a TypeError if you attempt to to an instanceof Foo check
Changing a property of an Object doesn't change the reference to that Object. e.g.
var foo = {},
bar = foo;
foo.hello = 'world';
foo === bar; // true
Changing the Object itself does change the reference
foo = {hello: 'world'};
foo === bar; // false
Or written in a way more closely to how the prototype is referenced from an instance,
var Foo = {}, // pseudo constructor
bar = {},
baz = {};
var fizz = {}; // fizz will be our pseudo instance
Foo.bar = bar; // pseudo prototype
fizz.inherit = foo.bar; // pseudo inheritance
Foo.bar = baz; // pseudo new prototype
fizz.inherit === foo.bar; // false, instance inheritance points elsewhere
Current best practice for setting up an inheritance chain is not to use new, but to use Object.create
Apple.prototype = Object.create(Fruit.prototype);
If you need the Fruit constructor called on Apple instances, you would do
function Apple() {
// this instanceof Apple
Fruit.apply(this);
// ...
}
We have to understand what happen behind the line
var a = new Apple();
JavaScript adopts Prototype-based programming as its OOP style. That means, it creates a new object by cloning a former object, not by instancing a class. Given Gecko and Webkit JavaScript engines, here is what happen behind the "new" statement above:
var a = clone(Apple.prototype); // this is an analogy to memcpy() in C/C++
a.__proto__ = Apple.prototype; // useful for the instanceof checking
a.constructor = Apple; // a function
a.constructor(); // so "this" in the called function means "a"
So now, both a.color and Apple.prototype.color are references to the same function located at address, e.g., 0xABCD because the value 0xABCD was copied from Apple.prototype to a. Thus, calling a.color() will associate with the address 0xABCD, it has nothing to do with Apple.prototype, so you can freely assign Apple.prototype to null.
It turns out that the clone() function above is actually the well-known Object.create() function. Object.create() also includes the assignment for the __proto__ property.

defining method with prototype property and without prototype difference

please clarify the difference b/w this two codes
function Person(gender) {
this.gender = gender;
alert('Person instantiated');
}
Person.prototype.sayHello = function()
{
alert ('hello');
};
var person1 = new Person('Male');
var person2 = new Person('Female');
// call the Person sayHello method.
person1.sayHello()
and the second one is below where function define inside funciton (without prototype property)
function Animal(gender) {
this.gender = gender;
alert('animal instantiated');
this.sayToodle = function()
{
alert ('GOOOOOOO!!');
};
}
var Animal1 = new Animal('Male');
var Animal2 = new Animal('Female');
Animal1.sayToodle();
my more simple question are:
what is the difference?
define method inside or out side of a function. what is the effect?
if both same then which is the fine way to define this.
and what does prototype do?
Can we not define method of a obj out side of its function(CLASS)???
Defining a member inside the constructor (such as: this.name) gives only that instance of the object access to that member.
Defining a member inside the prototype allows all instances to "share" that property.
A way that helped me understand this was to define an array (or any other member that is not a method) inside the prototype, like so:
function Animal() {}
Animal.prototype = {
kids: [],
giveBirth: function() {
for(var i = 0; i < arguments.length; i++) {
this.kids.push(arguments[0]);
}
}
}
var cat = new Animal();
var giraffe = new Animal();
cat.giveBirth('kitten','another kitten','yet another kitten');
// cat.kids === ['kitten','another kitten','yet another kitten'];
// giraffe.kids === ['kitten','another kitten','yet another kitten'];
If you notice, the giraffe's kids were set (as kittens). Why is this? Because in this case, .giveBirth() accesses the prototype's kids array, which is shared by all instances.
What if we don't want to share the members, because the members are unique? You can do like so:
function Animal() {
this.kids = [];
}
Animal.prototype = {
giveBirth: function() {
for(var i = 0; i < arguments.length; i++) {
this.kids.push(arguments[0]);
}
}
}
var cat = new Animal();
var giraffe = new Animal();
cat.giveBirth('kitten');
// cat.kids === ['kitten']
// giraffe.kids == undefined
giraffe.giveBirth('baby giraffe');
// cat.kids === ['kitten']
// giraffe.kids === ['baby giraffe']
As you pointed out in the comments, part of how you decide to define the properties plays into memory usage; another part plays into what members you want to be "shared" across all instances.
To get a little more insight into prototypes (through understanding how new works), see What is the 'new' keyword in JavaScript?, on StackOverflow.
Here's a quote from there:
After a lot of searching, I have finally found out exactly what the
new keyword does, and it is 4 things:
It creates a new object. The type of this object, is simply object.
It sets this new object's internal, inaccessible, [[prototype]] property to be the constructor function's external, accessible,
prototype object.
It executes the constructor function, using the newly created object whenever this is mentioned.
It returns the newly created object, unless the constructor function returns a non-primitive value. In this case, that
non-primitive value will be returned.
Prototype members are shared among instances and members in the constructor function defined as this.something are instance specific.
When an instance need instance specific members (like Person.name) define it as this.name. When it can be shared (like a method sayName) define it on the prototype like: Person.prototype.sayName=function(){...
For more info on prototype and constructor functions you can check this answer.

Categories