Prototype keyword in Javascript - javascript

What is prototype property, and why is it necessary? So far, I have learnt that this provides public access to more intrinsic, and private prototype of the object; is that correct?
Also, what's the difference between following statements?
MyConstructor.age = 30;
MyConstructor.prototype.age = 30;
In short, I need a better understanding of keyword prototype.
Thanks

"Prototype" is something that plays a role in objects.
In Javascript, everything is an object. Every object has a kind, and thus inherits the prototype of that kind.
For example, take a simple array: var a = []. You can make operations with it, like a.push(10). Where does this push method come from? From the prototype of Array object, which a is.
You can add your own methods to Array objects just by defining them in the prototype object. For example:
Array.prototype.sortNum = function() {this.sort(function(a, b) {return a - b});};
This way you can do something like a.sortNum() with all arrays, even the ones created before you defined the sortNum method.
(Note: for compatibility reasons, it's usually not recommended to extend the prototype of native objects like Arrays. But this particular example is usually a welcome addition, as well as normalizing methods like map and forEach for older browsers.)
(Just never ever extend Object.prototype! Unless you don't care to mess up for...in statements, the in operator and these sort of cases.)
If you want to define your own classes, like the name MyConstructor suggests, you'll have to define its prototype to define the methods for all the instances of that class:
function MyConstructor(name) {this.name = name};
MyConstructor.prototype = {
print: function() {return this.name;}
};
var mc = new MyConstructor("foo");
alert(mc.print()); // alerts "foo"
You can define more than just functions in prototypes, too:
MyConstructor.prototype.age = 30;
alert(mc.age); // alerts 30
Watch out when you do this to define "default" object values, because changing it may cause a change in all instances of that class.
But this comes handy with Object.defineProperty:
Object.defineProperty(MyConstructor.prototype, "wholeString", {
get: function() {return this.name + "=" + this.age;},
set: function(v) {this.name = v.substring(3);}
});
alert(mc.wholeString); // alerts "foo = 30"
(Unfortunately, IE<9 allows this only for DOM objects...)
When you define MyConstructor.age = 30 instead, what you're actually doing is defining a member of the function MyConstructor, so mc.age would be undefined. Every instance of MyConstructor inherits the methods and members defined in MyConstructor.prototype, not the ones of the function MyConstructor.
There's much more to say, actually. Objects can be of a subclass of another class, thus inheriting the prototype of the superclass, too. For example, document.body is an instance of HTMLBodyElement, which is a subclass of HTMLElement, which is a subclass of Element and so on, until you get Object as the upmost superclass. So, document.body inherits all the methods defined in the prototype of HTMLBodyElement, HTMLElement, Element and Object. This is called the prototype chain.
Doing the same with custom objects is a bit tricky:
function Class() {};
Class.prototype.foo = function() {alert("foo");};
function Subclass() {};
Subclass.prototype = new Class();
Subclass.prototype.bar = function() {alert("bar");};
var a = new Class(), b = new Subclass();
a.foo(); // alerts"foo"
a.bar(); // throws an error
b.foo(); // alerts "foo"
b.bar(); // alerts "bar"
a instanceof Class; // true
a instanceof Subclass; // false
b instanceof Class; // true
b instanceof Subclass; // true

In JavaScript, function objects have a built-in .prototype property. The value of this property is an object. If the function is used as a constructor, the resulting instances inherit from that "prototype" object.
Example:
var Dog = function () {}; // the constructor function
Dog.prototype.bark = function () {}; // adding a method to Dog.prototype
var dog1 = new Dog; // creating a new instance
dog1.bark(); // the instance inherits the "bark" method from Dog.prototype
Note that the .prototype property (of function objects) is not the same as the [[Prototype]] internal property. All objects contain the latter. It's an internal reference to an object's prototype. (In the above example, the dog1 object's [[Prototype]] refers to Dog.prototype.) On the other hand, only function objects have a built-in .prototype property (which makes sense since only function objects can be used as constructors).

var foo = function () {};
foo.bar = 5;
foo.prototype.foobar = 10;
var x = new foo();
x.bar; // undefined
x.foobar; // 10
Edit: Also, you can then do
foo.prototype.foobar = 20;
x.foobar; // 20

Related

javascript prototypical inheritance confused

given the standard way of achieving inheritance like this
function BaseClass() {
}
function SubClass() {
BaseClass.call(this);
}
SubClass.prototype = Object.create(BaseClass.prototype);
SubClass.prototype.constructor = SubClass;
why is necesary to do
SubClass.prototype = Object.create(BaseClass.prototype);
and end up with something like
function F(){}
F.prototype = BaseClass.prototype;
SubClass.prototype = new F();
instead of just doing
Subclass.prototype = BaseClass.prototype;
Assigning values to things in JavaScript really just copies a reference (unless working with primitive types). So when you do this:
Subclass.prototype = BaseClass.prototype;
What you're really doing is assigning the prototype of SubClass to the same location in memory as the prototype of BaseClass, therefore any prototype related changes you make to SubClass will also affect BaseClass. Here's a little example:
function BaseClass() {
}
function SubClass() {
BaseClass.call(this);
}
SubClass.prototype = BaseClass.prototype;
SubClass.prototype.constructor = SubClass;
SubClass.prototype.subClassFunction = function(){
console.log("Added this to SubClass");
}
var baseObj = new BaseClass();
baseObj.subClassFunction(); // => "Added this to SubClass"
That's why you want to use
SubClass.prototype = Object.create(BaseClass.prototype);
because it will create a new and unique object with the specified prototype instead.
You can read more about how this function works here.
Object Reference!
Say BaseClass has a method toString:
BaseClass.prototype.toString = function() {
return 'foo'
}
But you redefine the toString method in SubClass:
SubClass.prototype.toString = function() {
return 'bar'
}
You'll expect:
var b = new BaseClass(), s = new SubClass()
b.toString() //=> 'foo'
s.toString() //=> 'bar'
But if you use assignment to create inheritance what you will get is:
var b = new BaseClass(), s = new SubClass()
b.toString() //=> 'bar'
s.toString() //=> 'bar'
Because BaseClass.prototype and SubClass.prototype now reference the same object
Inheritance, the __proto__ :
When an object SubClass inherits from another object BaseClass, in JavaScript that means that there is a special property SubClass.__proto__ = BaseClass.
Code :
function BaseClass() {
}
function SubClass() {
}
var BaseClass = new BaseClass();
var SubClass = new SubClass();
BaseClass.a = 5;
SubClass.b = 10;
SubClass.__proto__ = BaseClass;
console.log(SubClass);
Output :
Here, BaseClass is inherited by SubClass and BaseClass variable is accessable through the SubClass.
The syntax of JavaScript can be somewhat confusing. In JS, there isn't class inheritance but instance-based inheritance. An instance's parent is also called its prototype.
When you write instance.something or instance['something'], the JS engine looks at the instance to see if it has a member called something. If it doesn't, then it looks at the instance's prototype. If that object doesn't have the member something, it looks at the prototype's prototype, again and again until it finds the property or reaches an instance which inherits from null. In that case it will simply return undefined.
Functions have a special property called prototype which is something else. The function's .prototype is a simple object that has a constructor property which refers back to the function itself. When you create an object with the new keyword, that object's prototype will be set to the function's .prototype property. This is where the confusion comes from: the .prototype property of a constructor can be seen as the default prototype of all instances made with said constructor.
So when you add methods to a class by writing something like this:
MyClass.prototype.foo = function() {
alert('foo');
};
...you're actually storing the function in the prototype of all MyClass instances. When the JS engine looks at the instances of MyClass, it will look for the foo member which it won't find. Then it will look at the instance's prototype which happens to be set to MyClass.prototype and it will find the foo member and fetch it.
It's important to make the difference between an instance's prototype and a function's .prototype, but most people don't realize it. When they speak of a class's prototype, they're talking about MyClass.prototype. The instance prototype is accessible via __proto__ in many browsers, but that's not a standard feature of JavaScript and shouldn't be used in your code.
Now let's look at the code you're using to simulate class inheritance.
SubClass.prototype = Object.create(BaseClass.prototype);
SubClass.prototype.constructor = SubClass;
Object.create(parent) can be seen as a function that does this:
return {
__proto__ : parent
};
In other words, it creates a blank Object whose prototype is the passed object. Since all SubClass instances will inherit from Subclass.prototype, replacing SubClass.prototype with an object that inherits from BaseClass.prototype makes sure all SubClass instances also inherit from BaseClass.
However, as I said earlier, the default .prototype attribute of a function is an empty object whose .constructor is set to the function itself. So by manually setting the .constructor again, we're perfectly mimicking default prototype behavior. If we don't do that, then instance.constructor will return the first defined .constructor property down the prototype chain, which will be BaseClass. It doesn't really change anything in terms of behavior unless our code actually depends on the constructor property, but it's safer to have it.
As a final note, like others mentioned before I could finally post this answer, you can't just do SubClass.prototype = BaseClass.prototype; because then you wouldn't be able to add methods to the SubClass without adding them to the BaseClass.

The prototype property and inheritance in JavaScript

The prototype property and inheritance in JavaScript is not clear to me.
I have a function:
function User (name) {
this.name = name;
}
Questions:
1) Why one of the following is false and the other is true?
User.prototype.hasOwnProperty('name'); // false
User.hasOwnProperty('name'); // true
2) What is de difference between the followings:
User.constructor;
User.prototype.constructor;
3) What happens with the User.constructor and User.prototype.constructor if I override the prototype property like this:
User.prototype = {
changeName: function(newName) {
this.name = newName;
}
};
And what if I override it like this:
User.prototype = {
constructor: User,
changeName: function(newName) {
this.name = newName;
}
};
4) Is User a function or a prototype or what? The following site refers it as prototype: 'The following example creates a prototype ...'
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor
Thank you very much for your answers.
First you need to understand what a prototype is.
In Javascript, almost everything is an object.
Edit (thanks #Mathletics):
Primitive booleans, numbers, and strings are not objects
When you create an object in Javascript, by default, its prototype will be an Object.
So, if I do:
var obj = {};
console.log(obj.__proto__)
This yields:
Object {}
Pause:
To understand the difference between obj.prototype and obj.__proto__, please, refer to this thread.
The next step is to understand the concept of prototype chaining.
This is how inheritance is structured in Javascript. Basically, a prototype is the "parent" of another object, from which it derives methods and properties.
Imagine a scheme where a Rabbit inherits from Mammal, which inherits from Animal. Representing this in Javascript prototype chain would be like:
(Rabbit) -> (Mammal) -> (Animal) -> (Object) -> null
With code:
function Animal(){}
function Mammal(){}
function Rabbit(){}
Mammal.prototype = new Animal();
Rabit.prototype = new Mammal();
If you are able to understand these concepts, you might find the answers to your questions yourself, but I'll try to make it clearer:
1) why one of the following is false and the other is true?
User.prototype.hasOwnProperty('name'); // false
User.hasOwnProperty('name'); // true
You should read the hasOwnProperty method reference:
Every object descended from Object inherits the hasOwnProperty method. This method can be used to determine whether an object has the specified property as a direct property of that object[...]
This is a way to assure that the property you are looking for is defined within the object itself, not deeper in the prototype chain.
A contrary example would be:
console.log(User.hasOwnProperty('constructor'));
Since the constructor property is defined deeper in the prototype chaing, it is not an "own property" of User object.
In your case, name is a property defined within your User object, but not defined in the context of the global Object.
2) what is de difference between the followings:
User.constructor;
User.prototype.constructor;
The fist like takes the constructor of User, the second takes the constructor of its prototype (in this case, the global Object).
3) what happens with the User.constructor and
User.prototype.constructor if I override the prototype property like
this:
User.prototype = {
changeName: function(newName) {
this.name = newName;
}
};
Please, read this thread.
TL;DR: when you assing directly to the prototype, you are breaking the prototype chain an creating a new one. In the Rabbit example, if you at some point did:
Rabbit.prototype = {
// ...
};
Your new prototype chain would be:
(Rabbit) -> (Object) -> null
So, in your first example, User.prototype.constructor would yield:
function Object{}
In your second example, it would yield:
function User(name)
Got it?
4) is User a function or a prototype or what?
User is an object whose prototype is a Function object, whose prototype is a Object object.
Drawing it:
(User) -> (Function) -> (Object) -> null
Hope I've been clear.
"Everything" in JS is an object.
So a function is a special type of object and that type of object has a property called name which is why User.hasOwnProperty("name") returns true. It has nothing to do with the property of the User object that same function can create. Try calling it something else and you will see this to be the case.
Any object derives from another object, namely it's prototype. The prototype of a function has a constructor property and __proto__ property but no name property.
So Ùser.prototype.hasOwnProperty("name")` should return false
Since all properties of the prototype are derived you can do this User.constructor even though User.hasOwnProperty("constructor") would return false
1) why one of the following is false and the other is true?
User.prototype.hasOwnProperty('name'); // false, A
User.hasOwnProperty('name'); // true, B
The prototype object hasn't been given a name property and it doesn't have one by default (as User is not native), so this is false for the prototype.
The Constructor User is a Function and you've defined the name of the function as "User". This is set on the function object when it's interpreted.
Are you sure you're not confusing this with (new User('foo')).hasOwnProperty('name'); // true?
This last case, the instance of User has a name property which is "foo", as set by the constructor User.
2) what is de difference between the followings:
User.constructor;
User.prototype.constructor;
User.constructor is Function because User is a function.
User.prototype.constructor is undefined, but you'd normally reference it back at User. This is what would later be accessed as (new User).constructor; // User
3) what happens with the User.constructor and User.prototype.constructor if I override the prototype [...]
Nothing happens to User.constructor in either case.
As for User.prototype.constructor, it wasn't define previously
so remains undefined in the first case
is set to User in the second case
Please note that in both of these cases the entire prototype is now pointing at a different Object so existing instances will not see these changes and the previous prototype chain is no longer accessible to new instances.
4) is User a function or a prototype or what?
User is a function and is a constructor. In JavaScript we call certain functions constructors if they will be used to build (construct) instances.
It may be helpful for you to see a more abstract example,
// A function `Foo` which will be our Constructor
function Foo(baz) {
this.bar = baz;
}
// notice here we have `Foo.name; // "Foo"`
// Setting up reference to the constructor through the prototype
Foo.prototype.constructor = Foo;
// Setting up reference to some other shared property through the prototype
Foo.prototype.fizz = ['buzz'];
And then usage
var foo = new Foo('hello world');
foo.bar; // "hello world" (own)
foo.fizz; // ["buzz"] (inherited)
foo.constructor; // Foo (inherited)
var bar = new Foo();
foo.fizz === bar.fizz; // true, this is the same Object reference - it is shared
Don't be afraid to try things out in your Console!
Javascript, unlike other languages (Java, ecc.), isn't class-based, it doesn't provide any way to define a class (actually, the next Javascript, ES6-Harmony, introduces the class keyword but it's just a syntactic sugar on top of prototype inheritance and, at the moment, isn't available in any browser)...
So, Javascript implements the (aka) OOP (Object Oriented Programming) via Prototype Inheritance.
If you want to create a custom object, you need to use a function that defines it. Example:
var Person = (function() {
/**
* this is the Constructor (if you have in mind a class-based language)
**/
function Person() {}
return Person;
})(window);
Doing that we have defined a New Object Person and we can have multiple instances of it using the new operator:
var me = new Person();
var you = new Person();
//...
As all languages do, javascript objects can have Methods and Properties, methods and properties can be both of Instance and Class.
var Person = (function() {
function Person() {}
/**
* Static Method
**/
Person.sayCiao = function() {};
/**
* Static Property
**/
Person.ciao = 'Ciao';
/**
* Instance Method
**/
Person.prototype.sayHello = function() {};
/**
* Instance Property
**/
Person.prototype.hello = 'Hello';
return Person;
})(window);
As you can see (try in your console), using the prototype property we can define methods or properties that all objects created by calling new Person inherit.
1) why one of the following is false and the other is true?
Of course, statics methods or properties don't belong to the instance and hasOwnProperty returns true only when is called using the constructor function. Viceversa, instances methods or properties belong only to their instances and hasOwnProperty returns true only when is called using the new operator. This is the normal behaviour that you can meet in other programming languages.
Note: in ES6 the Function Object has a property name and this is the reason how your test returns true, but isn't referenced to the name property that you define in the Person Constructor (read more).
Example of usage:
var Person = (function() {
function Person(name) {
this.firstname = name
}
Person.prototype.firstname = '';
Person.factory = function(name) {
return new Person(name);
};
return Person;
})(window);
var hitmands = Person.factory('Giuseppe');
console.log('you are', hitmands);
var you = Person.factory('BatMan');
console.log('hitmands is', you);
console.info('Person has a name?', Person.hasOwnProperty('firstname'));
console.info('You have a name?', you.hasOwnProperty('firstname'));
The property prototype belongs to the prototype chain, this is the reason how your test return false... ({}).hasOwnProperty('prototype')... You can read more following this link.
Simply prototype and what it contains doesn't is own property of your object.
2) what is de difference between the followings (ecc.)
As someone said, one belongs to the function and the other to the prototype property.
3) what happens with the User.constructor and User.prototype.constructor if I override the prototype property like this (ecc.)
You can use that way to extend behaviour from one class to another...
Read more about this.

why instances doesn't inherit property added to constructor function without prototype keyword

in this example a property called 't' is added to speak function.Speak.t=5;when i call speak() it prints the value 5 via another function called show.But when i create new instance of Speak it doesn't inherit the property t.Why is that so??i mean if it is a property of Speak constructor all its instances should inherit it??
<html>
<body>
<script>
function Speak(){
show(Speak.t);
}
Speak.t=5;
function show(v){
console.log('value is : '+v);
}
Speak();
var s1=new Speak();
console.log(s1.t);
</script>
</body>
</html>
"i mean if it is a property of Speak constructor all its instances should inherit it?"
No. Its instances inherit from the constructor's prototype, not the constructor itself. JavaScript is prototype-based, not "Constructor-based". If you are familiar with other OOP languages, Speak.t will be similar to a public static property.
Changing it to Speak.protoype.t = 5 will add the property t: 5 to the prototype which will be inherited to all of its instances:
function Speak(){
show(this.t);
}
Speak.prototype.t = 5;
function show(v){
console.log('value is : '+v);
}
var s1 = new Speak(); //"value is : 5"
console.log(s1.t); //5
Since instances inherit from its constructor's prototype, you can actually achieve class inheritance by doing this:
function SpecialSpeak(){}
SpecialSpeak.prototype = new Speak();
This creates a Speak instance and assign it as the SpecialSpeak's prototype.
new SpecialSpeak() instanceof SpecialSpeak; //true
new SpecialSpeak() instanceof Speak; //true
Since all Speak instances will be updated if its prototype has changed, it will also update SpecialSpeak's prototype and also update all SpecialSpeak's instances.
var s = new SpecialSpeak();
s.v; //undefined
Speak.prototype.v = "text";
s.v; //text
This demonstrates how inheritance works in JavaScript. The chaining of prototypes is sometimes called a "prototype chain".
You might also want to check out this great article about inheritance.
Side note: Since all prototype chains must have a starting point,
Object.prototype instanceof Object; //false
Although Object.prototype is an object, it is the very top prototype (object) that everything* inherits from, therefore it's not an instance of Object. It is the Object!
* Starting from ES5, Object.create is introduced which lets you create objects that doesn't inherit from Object.prototype.
This happens because you don't set internally the value of t. You should instantiate the value of t inside the constructor of Speak like this :
function Speak(){
this.t = 5;
show(this.t);
}
function show(v){
console.log('value is : '+v);
}
Speak();
var s1=new Speak();
console.log(s1.t);
You could also attach the showmethod inside the constructor to access the prototype of it.
var Speak = (function() {
function Speak() {
this.t = 5;
this.show();
}
Speak.prototype.show = function() {
return console.log('value is : ' + this.t);
};
return Speak;
})();
var s1=new Speak();
console.log(s1.t);
When the new operator is called on a constructor function, the JavaScript engine executes a few steps behind the scene:
It allocates a new object inheriting from your constructor function's prototype
It executes your constructor function, passing the newly created object as this
If your constructor function returns an object, then it uses it. Otherwise it uses the this object.
At no time it considers the class properties attached to the constructor function. This is why Speak.t = 5 doesn't create an inherited property.
However, those pieces of code will do:
// By attaching `t` to the prototype
function Speak1() {}
Speak1.prototype.t = 5;
// By attaching `t` to the newly created object
function Speak2() {
this.t = 5;
}
// By returning an object containing `t` (thus overriding the formerly allocated this)
function Speak3() {
return {
t: 5
};
}
DEMO
You can read here for more information.
Since functions are just objects t becomes a property of the function Speak, which is not shared with the instances.
for e.g functions by default get a property called length ( gives arity of the function)
which will not be shared with the instances.
function Speak(){}
var obj = new Speak();
console.log("length" in Speak); // true
console.log("length" in obj); // false
you can see quite clearly the length is not shared with the instances.
In javascript the only way to have a property or a method shared is through the prototype pattern.
Creating a property this way, makes it behave like a static variable on Speak

Purpose of this Javascript prototype snippet

Sorry I can't phrase this better. But I ran across some code like the following:
MyObject.prototype = Object.create(MyObject.prototype);
MyObject.prototype.constructor = MyObject;
And I just can't seem to figure out what it does. MyObject is defined above it something like this:
function MyObject(options) {
this.someProp = someDefault;
this.otherProp = process(options.something);
// etc...
}
and it's always called as a constructor. I'm just wondering what benefit those first two lines provide and if it's a known pattern in Javascript.
I just can't seem to figure out what it does
It creates a new object that inherits from [the old] MyObject.prototype via Object.create and then overwrites MyObject.prototype with that. It also explicitly adds a .constructor property which actually should be existing already.
I'm just wondering what benefit those first two lines provide
None, unless before that snippet someone has corrupted the prototype (like MyObject.prototype = Object.prototype) and this is an attempt to fix it.
…and if it's a known pattern in Javascript.
Not like this. Using Object.create to set up the prototype chain for inheritance between constructor-defined "classes" is a known pattern, but then the constructors would be different on each side of the assignment.
The two lines of code provided seem to be an incorrect attempt of the use of prototypal inheritance, but I see where you're going with this and what you're trying to accomplish.
As we know, there are two ways in JavaScript to define objects that have properties and methods as members - the object literal notation and function notation. Using object literal notation, we don't have immediate access to the new keyword (think of this like using abstract classes in Java or C#). With function notation, we have access to the new keyword because the initial declaration of an object as a function serves as our constructor.
In ECMAScript 5, The Object object was given a method called create that provided developers a simple way to create a new object from an existing object declared with the object literal notation. (See documentation here). However, objects created in function notation have problems with this method because they are Function objects. The Object.create method is a great way to use simple inheritance, allowing access to the base properties and methods.
With function notation, once the new keyword is used, the result is not a function, but rather an object. For example, I can test this:
var Obj = function(){};
console.log(typeof Obj) // "function"
console.log(typeof new Object()); // "object"
Because of this, you can only inherit once (meaning the child object cannot be derived from):
var MyObject = new Object();
var anotherObj = new MyObject() // throws exception
To alleviate this problem, you need to follow three steps:
Create your child object in function notation (so you can create new instances of it using the new keyword and inherit from it).
Set the child object's prototype (an object) to the result of a new instance of the base object (which will be an object as well).
Set the constructor of the child object (which happens to be on the object's prototype) back to reference the Function of itself (which is a function prior to instantiation). If you don't do this, the constructor will remain an object, which cannot spawn new instances.
From here, you can create new instances of both the child and parent objects and derive from both, using the pattern. Here's a practical example:
var Vehicle = function(){};
Vehicle.prototype.start = function() {
return this.make + " " + this.model + " " + "started";
}
var Car = function(color, make, model) {
this.color = color;
this.make = make;
this.model = model;
}
Car.prototype = new Vehicle();
Car.prototype.constructor = Car;
var myCar = new Car("red", "chevy", "aveo");
myCar.start(); //"chevy aveo started"
I really don't see any benefit in doing that.
What it's doing is providing the new object with the previous objects methods. But it's coming from the same object...
Here is a good example of JS inheritance:
http://jsfiddle.net/aDCmA/2/
var App = (function(){
var Being = function() {
this.living = true;
this.breathes = function () {
return true;
};
};
var Robert = function() {
this.blogs = true;
this.getsBored = function () {
return "You betcha";
}
};
Robert.prototype = new Being();
return {
Being: Being,
Robert: Robert,
being: function(){ return new Being(); },
robert: function(){ return new Robert(); }
}
}());
Here is another question that is similar: inherit prototype methods from other classes without overriding own prototype methods
Credit to Robert Nyman for originally blogging about it: http://robertnyman.com/2008/10/06/javascript-inheritance-how-and-why/
Let's see line by line:
MyObject.prototype = Object.create(MyObject.prototype);
This redefines MyObject.prototype to an object that inherits from MyObject.prototype. This is unusual, because it makes no sense to inherit from itself.
MyObject.prototype.constructor = MyObject;
Since the previous line overwrote MyObject.prototype, this is just fixing the constructor property that was lost in the process.
I can think of one scenario where tht might be useful: if some code before that messed up with MyObject.prototype, for example assigning the prototype of another constructor to it:
MyObject.prototype = SomethingElse.prototype; // wrong way to do inheritance.
Then the code you posted would be an attempt to fix it.
This is perfectly valid Javascript.
Any javascript function (say Func)can be used as a constructor and the constructor invocation also requires a prototype property (i.e. F.prototype or the prototype associated with the function) . Thus (almost) every function has a prototype property. The value of this property (i.e. Func.prototype).
Now the value of this prototype associated with the function is an object itself that has a single non enumerable property called constructor. And the value of this constructor property is the function object (i.e. F itself).
Lets take an example.
Say I construct a function Func
var Func = function() {
//your definition
};
Now since this can be invoked as a constructor it has to have a prototype property Func.prototype lets call this proto.
proto = Func.prototype;
Now the prototype has a single property (that is non enumerable) called constructor. This constructor has a value that is equal to the function object itself.
Dont believe me check it like this
Func.prototype.constructor === Func // =>true
Will always return true for any function.
Now from the code you explained :
So basically these two lines
MyObject.prototype = Object.create(MyObject.prototype);
MyObject.prototype.constructor = MyObject;
are modifying the value of the prototye to have a constructor property with the value of MyObject that is defined. But that would have happened anyways in the normal course of things. But the reason could be that maybe the prototype of the object has been changed earlier from the class it has been inherited from. In that case would those two lines make sense.
Hope that helps :)

JavaScript: how to access the prototype of a constructor function?

Maybe silly question to the JS gurus and ninjas out there but here goes:
My understanding of the prototype object/property of an object is that it is a blueprint for future instances of an object. Given this, shouldn't a newly created instance of an object be identical to the constructor object that created it?
var x = new Object();
console.log(x === Object.prototype); // returns false. why??
* UPDATE *
So understanding that this will return false because they are referencing different things, I still find that new Object() and Object.prototype contain a different number of properties. So to refine my question: How do I correctly check the number of properties in a prototype Object; how do I iterate through them?
The reason I got confused by this is that if I create a simple constructor function:
function Circle(){
this.tail = "yes, has tail";
}
and want to get the number of properties it has, doing something like:
console.log(Object.getOwnPropertyNames(Circle.prototype));
// returns "constructor", I expected it to return "tail"
=== does not answer the question of whether two things are equivalent, but whether they are references to the same object.
x and Object.prototype in your example may have the same properties, so you can call them equivalent, but they are two different objects.
If you do
x.foo = 3
they are now no longer equivalent, because they were two different objects. You changed one but not the other.
If
x === Object.prototype
were true, then
x.foo === Object.prototype.foo
would be the same regardless of what you assign to x.foo or Object.prototype.foo.
EDIT:
function Circle(){ this.tail = "yes, has tail"; }
console.log(Object.getOwnPropertyNames(Circle.prototype));
// returns "constructor", I expected it to return "tail"
There is no tail property on Circle.prototype because you have never done Circle.prototype.tail = ...;. You define tail only on Circle instances via this.tail = ...;.
I still find that new Object() and Object.prototype contain a different number of properties.
You are also doing getOwnPropertyNames. The own properties are those that are not inherited from the prototype, so by using that function on x you are explicitly excluding all the properties of Object.prototype.
The docs for hasOwnProperty explain "own property" pretty well:
This method can be used to determine whether an object has the specified property as a direct property of that object; unlike the in operator, this method does not check down the object's prototype chain.
console.log(Object.getPrototypeOf(x) === Object.prototype); // true
If you want to get the hidden property [[Prototype]] that points to the next element in the prototype chain for an object just call Object.getPrototypeOf.
Also you mis-understand how the prototype chain works.
For any given object, if you look up a property it will first look at that object. It will then (recursively) look at the objects [[Prototype]] value for whether it has that property.
Example prototype chains :
var o = new Object();
// o -> Object.prototype -> null
var a = new Array();
// a -> Array.prototype -> Object.prototype -> null
var Super = function () {};
var Child = function () {};
Child.prototype = Object.create(Super.prototype);
var c = new Child();
// c -> Child.prototype -> Super.prototype -> Object.prototype -> null
x is an instance of "Object". You probably want to check if x has a Object as constructor. Prototype isn't constructor.
Try this
var x = new Object();
console.log(x.constructor === Object);
Regarding your update:
this within a constructor function is the instance created with the new keyword, not the prototype.
So, in the case of your snippet...
function Circle(){
this.tail = "yes, has tail";
}
Setting this.tail is similar to:
var c = new Circle();
c.tail = "yes, has tail";
tail is only a property of the instance.
To set tail on the prototype, you must use:
Circle.prototype.tail = "yes, has tail";
Now, "Own" properties are those set directly on the instance. These counter and override prototype properties of the same name:
function Circle() {
// give the instance its "own" `foo` property
this.foo = 'qux';
}
Circle.prototype.foo = 'foo';
Circle.prototype.bar = 'bar';
var c = new Circle();
console.log(c.foo); // the overridden "qux", not the inherited "foo"
console.log(c.bar); // "bar", as inherited
// yet the prototype still persists to have its "own" `foo`
console.log(Circle.prototype.foo); // "foo"
// While the instance has keys for all involved properties
console.log(Object.keys(c)); // [ "foo", "bar" ]
// It also retains which are its "own"
console.log(Object.getOwnPropertyNames(c)); // [ "foo" ]

Categories

Resources