I want to achieve a extend method on a constructor function, and use it to initialize an instance, like:
var view_instance = View.extend()
so I tried this:
define(function (require, exports, module) {
function View(size, color) {
this.size = size;
this.color = color;
};
View.prototype = {
show: function () {
console.log("This is view show");
}
}
View.extend = function (props) {
var tmp = new this("12", "red");
console.log(this);
console.log(tmp instanceof this) //true
console.log(tmp.prototype); //undefined!
return tmp
}
return View;
})
in the above extend method, I initialize an instance through new this(), but I can't log its prototype, and I check the this is right.
So what's wrong with my code? Why the prototype disappear? How can I do it right?
There's nothing wrong with your code. It does what it's supposed to do. The prototype property only exists on functions.
When you precede a function call with the new keyword JavaScript creates an object which inherits from the prototype of the constructor.
To put it in simple terms:
function F() {} // we have a constructor
var o = new F; // we create an instance
console.log(Object.getPrototypeOf(o) === F.prototype); // o inherits from
// F.prototype
Objects in JavaScript inherit from other objects via delegation. This means say we try to access a property on the object o which we saw above:
JavaScript will first try to find the property on o itself.
If it can't find the property on o then it will try to find it on Object.getPrototypeOf(o) (or to put it more succinctly o.__proto__). The prototype of o is F.prototype.
If it can't find the property on F.prototype then it will try to find it on F.prototype.__proto__ which is Object.prototype.
If it can't find the property on Object.prototype then it will give up because Object.prototype.__proto__ is null.
That is prototypal inheritance for you in a nutshell.
The reason your code logs undefined for tmp.prototype is because tmp doesn't have any property called prototype. Only functions have a prototype property. Try this instead:
console.log(Object.getPrototypeOf(tmp));
The above is the same as the following. However the __proto__ property of objects is deprecated. Use it at your own risk:
console.log(tmp.__proto__);
If you want to learn more about inheritance then read the following articles:
Aadit M Shah | Why Prototypal Inheritance Matters
JavaScript inheritance and the constructor property - Stack Overflow
tmp.constructor.prototype is what you want. o.__proto__ is just a shortcut for o.constructor.prototype and it's non-standard.
[EDIT]
You can see the figure in this question. It shows that Foo.prototype.constructor points to Foo itself. However, since you are overwriting the prototype of the constructor with the line View.prototype = {...}, View.prototype.constructor will be function Object() { [native code] } instead of View itself. So a more accurate way would be assigning properties to the original prototype directly or overwriting it with the constructor property set manually:
// Assign properties to the original prototype to prevent overwriting the `constructor` properties.
View.prototype.show = function() {};
// Or set the constructor manually.
View.prototype = {
show: function() {},
constructor: View
};
The prototype property belongs to constructors. The instances have a non-standard __proto__ property pointing to the same object. So:
console.log(tmp.__proto__);
Or:
console.log(Object.getPrototypeOf(tmp));
Related
I am confused, can somebody guide, in javascript, if prototype property of Function object (Function.prototype) doesn't have a prototype property then, how come a user defined function, automatically have its prototype property. like
function f(){
}
f.prototype.
Thanks
Almost all objects in JavaScript have the prototype property. By using it and more specifically the prototype chain we can mimic inheritance. The prototype is a reference to another object and it is used whenever JS can’t find the property you’re looking for on the current object. Simply put, whenever you call a property on an object and it doesn’t exist, JavaScript will go to the prototype object and look for it there. If it finds it it will use it, if not it will go to that object’s property and look there. This can bubble up all the way to Object.prototype before returning undefined. This is the essence of the prototype chain and the behavior that sits behind JavaScript’s inheritance.
function Animal(name) {
this.name = name;
}
Animal.prototype.sleep = function() {
console.log(this.name + ': Zzz...');
}
function Dog(name) {
this.name = name;
}
// Create a reference for the prototype
Dog.prototype = Object.create(new Animal());
Dog.prototype.makeSound = function() {
console.log(this.name + ': Woof woof!');
}
var dog = new Dog('Lassie');
dog.makeSound(); // Lassie: Woof woof!
dog.sleep(); // Lassie: Zzz...
dog.missing(); // Throws Error
Full reference:https://hackernoon.com/understanding-javascript-prototype-and-inheritance-d55a9a23bde2
In fact, Function object do have a prototype property, this is an excerpt from the MDN Inheritance and prototype chain:
function f() {
return 2;
}
// Functions inherit from Function.prototype
// (which has methods call, bind, etc.)
// f ---> Function.prototype ---> Object.prototype ---> null
For better understanding of the prototype chain, I recommend you read the following post: JS Prototype chain mechanism.
AFAIK, JS provides inheriatnce by means of assigning a prototype chain to a newly created object. So, the code below seems to be the correct way to me:
function Animal(name){
this.name = name;
}
Animal.prototype.getName = function(){return this.name;};
function Cat(){
Animal.apply(this, arguments);
}
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;
Cat.prototype.sayHi = function(){return 'Hi, my name is '+this.name+', and I am a "'+this.constructor.name+'" instance';};
Is this actually correct? And, I've read, that mutating object's prototype is a slow discouraged operation, that affects all the later calls to it. But here we've just mutated Animal.prototype and Cat.prototype. So, is that bad? If it is how do we deal with it? Or I've misunderstood something about that prototype mutating warning? If so, what does it actually mean?
Is this actually correct?
In that it doesn't contain anything that might be considered poor practice, yes. Whether it's correct in terms of the outcome being what you expected can't be determined.
And, I've read, that mutating object's prototype is a slow discouraged operation,
I have no idea what that means. However, it's not considered good practice to modify objects you don't own, so don't go messing with built–in or host objects (there are many articles on why not, e.g. What's wrong with extending the DOM and Extending builtin natives. Evil or not?).
that affects all the later calls to it.
Modifying a prototype may affect all objects that have it as their [[Prototype]], that's the point of prototype inheritance.
But here we've just mutated Animal.prototype and Cat.prototype. So, is that bad?
Of itself, no. If it achieves the outcome you require, then fine. You're defining the constructor, prototype properties and inheritance scheme, so it's up to you. There might be more efficient or more easily maintained schemes, but that's another topic.
Comment
Complex inheritance schemes are rarely useful in javascript, there just isn't much call for it. Most built–in objects have only one or two levels of inheritance (e.g. function instances inherit from Function.prototype and Object.prototype). Host objects (e.g. DOM elements) may have longer chains, but that is for convenience and not really necessary (at least one very popular browser didn't implement prototype inheritance for host objects until recently).
You're on the right track. You don't want to mutate Animal's prototype because that breaks the concept of inheritance. As was mentioned in the comments, using Object.create() is the correct way to inherit properties and methods from one object to another. A simple example of prototypical inheritance, using your example, is achieved this way:
function Animal(name) {
this.name = name;
}
Animal.prototype = {
getName: function() {
return this.name;
}
};
function Cat(name, color) {
Animal.call(this, name);
this.color = color;
}
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;
Cat.prototype.getColor = function() {
return this.color;
};
var animal = new Animal('Bob');
var cat = new Cat('Tabby', 'black');
console.log(cat.getName());
console.log(cat.getColor());
console.log(animal.getName());
console.log(animal.getColor()); // throws an error
Hi inheritance in JavaScript is rather complex and you will have to have a good understanding of the prototype object. Ill suggest you use the inheritance pattern of for instance TypeScript. You can give it a try on the Playground
Take a look at this:
var extends = this.extends || function (class, parent) {
for (var property in parent) {
if (parent.hasOwnProperty(property)) {
class[property] = parent[property];
}
}
function newClass() {
this.constructor = class;
}
newClass.prototype = parent.prototype;
class.prototype = new newClass();
};
var Animal = (function () {
function Animal(name) {
this.name = name;
}
return Animal;
})();
var Cat = (function (_super) {
extends(Cat, _super);
function Cat(name) {
_super.call(this, name);
}
Cat.prototype.sayHi = function () {
return "Hello my name is:" + this.name;
};
return Cat;
})(Animal);
You seem to be mixing the prototype property of functions with the internal [[proto]] property of all objects (including functions). They are two distinct things.
Mutating the internal [[proto]] property of an object is discouraged. This can be done either via setPrototypeOf or via the __proto__ accessor, which is inherited from Object.prototype:
var a = {}; // `a` inherits directly from `Object.prototype`
var b = {}; // `b` inherits directly from `Object.prototype`
a.__proto__ = b; // `a` now inherits directly from `b`
// or
Object.setPrototypeOf(a, b); // `a` now inherits directly from `b`
This is what is discouraged, mutating the internal [[proto]] property of an object after it has been created. However, it should be noted that while the object is being created it's alright to assign any object as its internal [[proto]] property.
For example, many JavaScript programmers wish to create functions which inherit from some object other than Function.prototype. This is currently only possible by mutating the internal [[proto]] property of a function after it has been created. However, in ES6 you will be able to assign the internal [[proto]] property of an object when it is created (thus avoiding the problem of mutating the internal [[proto]] property of the object).
For example, consider this bad code:
var callbackFunctionPrototype = {
describe: function () {
alert("This is a callback.");
}
};
var callback = function () {
alert("Hello World!");
};
callback.__proto__ = callbackFunctionPrototype; // mutating [[proto]]
callback.describe();
It can be rewritten in ES6 as follows:
var callbackFunctionPrototype = {
describe: function () {
alert("This is a callback.");
}
};
// assigning [[proto]] at the time of creation, no mutation
var callback = callbackFunctionPrototype <| function () {
alert("Hello World!");
};
callback.describe();
So, mutating the internal [[proto]] property of an object (using either setPrototypeOf or the __proto__ accessor) is bad. However, modifying the prototype property of a function is fine.
The prototype property of a function (let's call the function F) only affects the objects created by new F. For example:
var myPrototype = {
describe: function () {
alert("My own prototype.");
}
};
function F() {}
var a = new F; // inherits from the default `F.prototype`
alert(a.constructor === F); // true - inherited from `F.prototype`
F.prototype = myPrototype; // not mutating the `[[proto]]` of any object
var b = new F; // inherits from the new `F.prototype` (i.e. `myPrototype`)
b.describe();
To know more about inheritance in JavaScript read the answer to the following question:
JavaScript inheritance and the constructor property
Hope that helps.
I've been reading up on the Crockford shim for preventing the overwriting of prototypes, and understand that it's not the end-all/be-all solution at times. I also understand that ES5 Shim may be a viable alternative to this. I also read this post which provides a more robust, secure alternative.
Still, I'd like to know what his Object.create shim is "saying" and then "doing." Can someone please tell me if my explanation comments are right?
if (typeof Object.create === 'undefined') {
//If the browser doesn't support Object.create
Object.create = function (o) {
//Object.create equals an anonymous function that accepts one parameter, 'o'.
function F() {};
//Create a new function called 'F' which is just an empty object.
F.prototype = o;
//the prototype of the 'F' function should point to the
//parameter of the anonymous function.
return new F();
//create a new constructor function based off of the 'F' function.
};
}
//Then, based off of the 'Lost' example in the Crockford book...
var another_stooge = Object.create(stooge);
//'another_stooge' prototypes off of 'stooge' using new school Object.create.
//But if the browser doesn't support Object.create,
//'another_stooge' prototypes off of 'stooge' using the old school method.
This way, the prototype of the 'stooge' object can't be overwritten when we augment stuff to 'another_stooge'. No need to reset the 'stooge' prototype using 'constructor'.
Thanks in advance,
-k
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}
var oldObject={prop:'Property_one' }; // An object
var newObject = Object.create(oldObject); // Another object
In the above example we've created a new object newObject using create method which is a member function of Object object that we've added in the Object object earlier in our (Crockford's) example. So basically what it does is that, the create method declares a function F, an empty object every function is a first class object in javascript and then we've inherited the prototype of o (in that case o is also an object oldObject passed as the parameter of create method) and finally we've returned the new object (an instance of F) using return new F(); to the variable newObject, so now newObject is an object that inherited the oldObject. Now if you write console.log(newObject.prop); then it'll output Property_one because our newObject object has inherited the oldObject and that's why we've got the value of prop as Property_one. this is known as prototypical inheritance.
You must pass an object as the parameter of create method
All it does is create a new object constructor, which is F, it then assign the passed object to the constructor prototype property so that new object created with the F constructor inherit those methods.
It then use the constructor to return an newly initialize object (new F() => F.prototype)
But the crockford one fail to reassign the constructor properly as normally the new object constructor should be the same as the object constructor it inherits from.
On your comments:
> //Object.create equals an anonymous function that accepts one parameter, 'o'.
Better to say that a function is assigned to the create property of Object. All functions can be considered anonymous, just that some are assigned to named properties or variables, others aren't.
> //Create a new function called 'F' which is just an empty object.
Declare a function. Yes, it's an object too.
> F.prototype = o;
> //the prototype of the 'F' function should point to the
> //parameter of the anonymous function.
A reference to o is assigned to F.prototype is a bit shorter to write.
> //create a new constructor function based off of the 'F' function.
No, should be "Return an instance of F". So the returned object has an internal [[Prototype]] that references the object passed to the function. The messy part is that a useless F function had to be created to perform the trick, and the returned object's constructor will not have a useful value as it references the empty F.
Not that the constructor property is very reliable or particularly useful normally anyway.
This way, the prototype of the 'stooge' object can't be overwritten
when we augment stuff to 'another_stooge'. No need to reset the
'stooge' prototype using 'constructor'.
That's a strange statement. *another_stooge* has stooge as it's private [[Prototype]], it does not inherit from stooge.prototype but from stooge.[[Prototype]].
If you want another_stooge to inherit from stooge.prototype, use Object.create(stooge.prototype) or Object.create(new stooge()), the former is probably more suitable.
I hope that all makes sense.
There are two tricks here:
F is not a simple function, it is a constructor.
"F.prototype" is just a property, it does nothing with inheritance in this moment.
The real trick is that when we use "new F()", the "new" creates a new object, calls the constructor (which does not do anything here) AND sets the new object's internal "prototype" field with the value of "F.prototype", so the returned object will inherit from "o".
So I think, that:
F is a constructor
F is not inherit from o
"new F" (which is the returned object) is inherit from o
I guess naming the internal function as Object instead of F makes the resulting object look closer to what Object.create() would create.
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function Object() {}
Object.prototype = o;
return new Object();
};
}
Can someone explain this?
function Foo() {
this.x = 1;
this.y = 2;
}
function FooProto() {
this.arrow = 1;
this.bow = 1;
}
document.writeln(Foo.prototype); // [object Object]
document.writeln(Foo.prototype.constructor); // function Foo() { x =1; y=2; }
My understanding here is: Foo.prototype is an Object whose constructor property is Function Foo. Foo.[[Prototype]] is Function.Prototype
obj = new Foo;
document.writeln(obj.constructor); // function Foo() { x =1; y=2; }
document.writeln(obj.constructor.prototype); // [object Object]
Foo.prototype = FooProto;
document.writeln(Foo.prototype); // function FooProto() { arrow = 1; bow = 2; }
document.writeln(Foo.prototype.constructor); // function Function() { [native code] }
Question 1: How did the look up using [[Prototype]] happen here. I would appreciate if someone can explain this to me.
document.writeln(obj.constructor); // function Foo() { x =1; y=2; } .. no change
document.writeln(obj.constructor.prototype); // function FooProto() { arrow = 1; bow = 2; }
anotherObj = new Foo;
document.writeln(anotherObj.constructor); // function Function() { [native code] }
document.writeln(anotherObj.constructor.prototype); // function Empty() {}
Question 2: Same question as Question 1. How did the Javascript interpreter perform the lookup?
When explaining prototype-based code, it is much simpler to use Object.create to explain stuff. Object.create is a function that receives a prototype object and creates a new instance object that has the prototype object as its [[prototype]]
When looking up properties in an object is work like this:
Every object has its own and immutable [[prototype]] property inside. This property is secret and hidden, unless you are in Firefox, where you can get it via __proto__.
When reading a property up we first search for it in the object itself and if we don't find it there we recursively search for the object's [[prototype]].
When writing a property we always write an own-property (we never mutate the [[prototype]], even if it also has the property we are setting).
proto = {a:1};
child1 = Object.create(proto);
child2 = Object.create(proto);
child1.a = 2;
console.log(proto.a); //1
console.log(child1.a); //2
console.log(child2.a); //1
When creating a function
Whenever we create a function object in Javascript, it comes with a prototype property already filled in. This prototype is an object (inheriting from Object.prototype) and has the constructor property set to the corresponding function.
When instantiating an object using a function constructor (new Foo)
A new object is created with the functions prototype as its [[prototype]] and the function is run o the object to initialize it.
I don´t really want to explain what is going on in the first case, since the
Foo.prototype = FooProto; part doesn't really make sense and is probably not what you wanted to do (remember that prototypes should be objects, not functions)
As for the second case, changing the prototype property of the constructor function will only affect the future instances (anotherObj). The [[prototype]] property of the already created objects is secret and immutable so there is nothing you can do to change them.
Note that if you want to dynamically change the prototype and existing objects (monkey-patching) you can do that by writing and overwriting values in the existing prototype object instead of replacing it with a new one.
There're two concepts of prototype in Javascript. (I take it as a name collision in language design.)
The prototype in the "prototype chain".
It is a inside property as mentioned in the last answer. The prefered way to access it is Object.getPrototypeOf.
var a = {};
Object.getPrototypeOf(a); // Object {}
Object.getPrototypeOf(Object.getPrototypeOf(a)); // null, the top of prototype chain.
Object.getOwnPropertyNames(Object.getPrototypeOf(a)); // the methods inherited
Every constructor (I think acutally every function declared) has a own property "prototype". It come to use in the new operator.
The new operator does 2 steps.
First is to create an object whose prototype (the 1st one, saying, [[Prototype]]) is assigned as the constructor's prototype (the 2nd one).
Second is to run the constructor (looking up from prototype.constructor) with taking the created object as implicit argument this.
Now to your case:
The first obj was created with its property [[Prototype]] (proto in some engines) assigned as Foo.prototype.
obj.constructor === obj.__proto__.constructor === Foo.prototype.constructor === Foo
obj.constructor.prototype === Function.prototype
Note that the constructor is also a Function object.
Then you changed the prototype of Foo. This changed the obj.constructor.prototype but not obj.constructor which has a different reference. The anotherObj had a new [[Prototype]] from the following new operator.
This question has been here for years. Following readers may be also confused as me. I recommendated the newly published book Speaking JavaScript from Dr. Axel Rauschmayer :
Terminology: The Two Prototypes
I asked the question:
Why cant I declare a constructor instantiate an object and then access the prototype?
And you can see that I have marked the answer. I understand the response but Im a bit confused as to what he means by:
The prototype belongs to the class, not the instance:
Does this mean that javascript has a class in this example? I thought javascript was classless? It only has function constructors... At what point does a function constructor become a class? Is it when you add other members to it using the .prototype accessor?
Actually class is an OOP term, not really javascript. What is meant is that the prototype belongs to the constructor. So in
function MyConstructor(prop){
this.foo = prop || 'foo';
}
MyConstructor.prototype.bar = 'allways bar';
var mc1 = new MyConstructor('I am mc1'),
mc2 = new MyConstructor('I am mc2');
alert(mc1.bar) ; //=> allways bar
alert(mc2.bar) ; //=> allways bar
alert(mc1.foo) ; //=> I am mc1
alert(mc2.foo) ; //=> I am mc2
bar belongs to the constructors (MyConstructor) prototype. It will always be 'allways bar', for every instance. foo is an instance property (with a default value 'foo') and can be assigned with a different value for every instance.
Ya prototype of JavaScript is a concept quite similar to class but not exactly the same. Read the article below, it offers one of the best explanations available on internet on this issue.
http://www.crockford.com/javascript/inheritance.html
There are no classes in javascript.
Constructors are functions and have a prototype property that references an object. You can add functions to that object, or assign a new object to the prototype property to create an inheritance chain:
function MyConstructor () {
// initialise instance
}
MyConstructor.prototype.someMethod = function() {
// ...
};
MyConstructor.prototype.anotherMethod = function() {
// ...
};
or replace it with an instance of another constructor:
MyConstructor.prototype = new SomeOtherConstructor();
MyConstructor.prototype.constructor = MyConstructor;
and so on. Now when an instance of MyConstructor is created:
var anInstance = new MyConstructor();
The object returned by the constructor has MyConstructor.prototype as its internal [[prototype]] property and "inherits" its methods and properties (and those on its entire [[prototype]] chain).
So each instance of MyConstructor has its MyConstructor.prototype on its prototype chain. Note however that MyConstructor doesn't inherit from it's own prototype, it is only used by instances created by new MyConstructor.