I always thought that a prototype had some magic around it, but it seems that a prototype is actually just an object attached to a function. As an example:
function someMethod() {};
function Person(name) {
Object.assign(this, {name});
}
Person.prototype.number = 4;
Person.prototype.letter = "a";
Person.prototype.method = someMethod;
let obj = {
number:4,
letter:'a',
method: someMethod
};
console.log(`\
${Object.entries(Person.prototype).toString()}
${Object.entries(obj).toString()}
${Object.entries(Person.prototype).toString() == Object.entries(obj).toString()}\
`);
Is that more or less a correct understanding of what the prototype is? Or does any other machinery go on behind the scenes that the obj in the above example does not include?
A .prototype object is indeed just an ordinary object. It is used in prototype chains like any other object can be used in them.
The only "magic" behind implicitly created .prototype objects on functions is that they have a non-enumerable .constructor property that points back to the function.
function Person() {}
let obj = {};
console.log(Object.hasOwn(obj, 'constructor'));
console.log(Object.hasOwn(Person.prototype, 'constructor'));
Related
Im new to javascript ; and im digging into 'new' variable.
My qustion is :
function Fruit(name)
{
this.name = name;
}
function myNew(con,args){
var obj = {};
obj = con.apply(obj,args) || obj;
obj.constructor = con;
return obj;
}
var f1 = new Fruit("Mango");
var f2 = myNew(Fruit,["Orange"]);
console.log(f1.name, f1 instanceof Fruit);
console.log(f2.name, f2 instanceof Fruit);
now the output im getting is :
Mango true
Orange false
what I need to do if I need output :
Mango true
Orange true..
I need some explanation here.
I dont know if somebody already answered this question but i was unable to find it.
Lets say we have Foo constructor.
function Foo(options) {
// constructor
this.name = options.name;
}
// and create instance of it
var foo = new Foo({name: "Foo"});
From the MDN reference, "new" operator does:
A new object is created, inheriting from Foo.prototype.
The constructor function Foo is called with the specified arguments and this bound to the newly created object. new Foo is equivalent to new Foo(), i.e. if no argument list is specified, Foo is called without arguments.
The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new
So basically it setups object prototype and executes constructor function, returning an object, unless constructor doesn't return anything else.
"apply" function instend, only runs function in specific context. It doesn't setup inheritance. In you case it just runs constructor in context of your custom obj.
var obj = {};
You can see this on this fiddle:
http://jsfiddle.net/hp244jn7/
There "_ proto _" property used, to see whats in prototype chain. Don't use it in development.
If you want the desired effect you should probably use what giorgio suggested.
You should use prototype property to define that your object is based on some other object
function myNew(con,args){
var obj = {};
obj = con.apply(obj,args) || obj;
obj.prototype = con;
return obj;
}
You're thinking to difficult ;) This is doing what you want:
function myNew(con, args) {
return new con(args);
}
see the demo here
I'm studying javascript and have a trouble to understand the 2nd part in the explanation below. Is it possible for any of you shed me the light on this matter
"The actual prototype of a constructor is function.prototype since constructors are functions. Its prototype property will be the prototype of instances created through it but is not its own prototype"
I think a series of comparisons will help you figure it out.
The actual prototype of a constructor is function.prototype since constructors are functions
function IamAConstructorFunc() {} // A constructor function
IamAConstructorFunc.constructor // function Function()
IamAConstructorFunc.constructor.prototype // function Empty()
IamAConstructorFunc.constructor.prototype === Function.prototype // True
IamAConstructorFunc.constructor.prototype === Object.prototy // False
Its prototype property will be the prototype of instances created through it
var IObj = new IamAConstructorFunc; // Instance of IamAConstructorFunc
IObj.__proto__ === IamAConstructorFunc.prototype // True
IObj.constructor === IamAConstructorFunc // True
IObj instanceof IamAConstructorFunc // True
but is not its own prototype
IamAConstructorFunc has a prototype but it's not it's own prototype, it's an instance of Object and that instance prototype is:
IamAConstructorFunc.prototype.__proto__ === Object.prototype // True
OK, here's an example:
function Widget() {
console.log('Widget constructor invoked');
}
Function.prototype.sayHi = function() { console.log('Function prototype.sayHi invoked'); };
Widget.prototype.sayHi = function() { console.log('Widget prototype.sayHi invoked') };
var w = new Widget();
console.log('Calling w.sayHi()');
w.sayHi();
console.log('Calling Widget.sayHi()');
Widget.sayHi();
This will produce the following log output:
Widget constructor invoked
Calling w.sayHi()
Widget prototype.sayHi invoked
Calling Widget.sayHi()
Function prototype.sayHi invoked
Calling w.sayHi() is calling a method on the Widget object, while calling Widget.sayHi() is invoking a method on a function. They have two different prototypes.
That's way too complicated.
A function can be used to create an object.
function MyFunc(a, b) {
this.a = a;
this.b = b;
}
var myObj = new MyFunc(a, b);
The function's prototype can be used to create functions that work on the object.
MyFunc.prototype.sum = function() {
return this.a + this.b;
}
var myObj = new MyFunc(2, 3);
var true = (myObj.sum() === (2 + 3));
It's probably easier viewing an example.
function Person(first, last) {
this.first = first;
this.last = last;
}
Person.prototype.fullName = function() {
return this.first + " " + this.last;
}
var fred = new Person("Fred", "Flintstone");
var barney = new Person("Barney", "Rubble");
var output = document.getElementById("output");
output.innerHTML += fred.fullName() + "<br>\n";
output.innerHTML += barney.fullName() + "<br>\n";
#output {
color:blue;
font-weight:bold;
}
<div id="output">
</div>
I think the problem is the confusion between the prototype property of a function and the internal prototype, that every object has.
Every function has a prototype property. This property is like any other property of any object. The only thing special about it is, that it will be used as the internal prototype for any object, that is created by that function.
function A() {
}
//add property c to public prototype property of A
A.prototype.c = 1;
//create a new instance -> a will get A's prototype property as internal prototype
a = new A();
//a has therefore access to the property c, that was defined earlier
console.log(a.c); //1
Since functions are also objects in JavaScript, they also have an internal prototype.
function A() {}
//apply is part of A's prototype chain.
//It's defined on its internal prototype objects,
//which was created by its own constructor, named "Function"
A.apply(this, []);
This statement almost drove me crazy but I ended up understanding it. In fact, in JavaScript, a constructor, when created get automatically assigned a property called prototype.
This property will be used by all instances created through this constructor as their own prototype and DOES NOT REFER ANYWAY TO the actual prototype of the constructor itself. Actually, the constructor prototype is Function.prototype.
var Cat = function() {};
Cat.__proto__ === Function.prototype; // true
var kitty = new Cat;
kitty.__proto__ === Cat.prototype; // true
It is normal because the Cat (our constructor) is a Function per se so it derived from Function.prototype. And kitty came out of the new keyword call on Cat so it derived from Cat.prototype.
So in the statement :
The actual prototype of a constructor is function.prototype since constructors are functions.
The actual prototype refers to __proto__ property of our constructor (Cat).
Its prototype property will be the prototype of instances created through it but is not its own prototype.
Its prototype property refers to .prototype
Using JavaScript, is it permissible to use a function as a prototype, e.g.
function Foo(){
}
Foo.prototype = function(){
}
or is it required to use
Foo.prototype = { };
and more importantly, does it make an important difference?
Yes both ways are permissible because of flexibility nature of JavaScript prototypical inheritance. First let's look at the prototypical chain for the both cases. I am considering only literal objects for the simplicity.
Object.prototype vs Function Prototype
The last value of __proto__ (internal [[Prototype]]) for the objects created using literal is Object.prototype eventually. For example:
/*Example 1*/
var o = { foo: 1, bar: 2 }
Prototypical chain: o -> Object.prototype
/*Example 2*/
var o = { foo: 1, bar: 2 }
o.__proto__ = { another:3 }
Prototypical chain: o ->o.__proto__ -> Object.prototype
For functions, the last value of __proto__ is Object.prototype as well except it has always a preceding value Function.prototype. For example:
/*Example 1*/
function Foo () {
return xyz;
}
Prototypical chain: Foo -> Function.prototype -> Object.prototype
/*Example 2*/
function Foo () {
return xyz;
}
Foo.prototype = { another:3 }
Prototypical chain: Foo -> Foo.prototype -> Function.prototype -> Object.prototype
For option 1:
function Foo(){
}
Foo.prototype = function(){
}
As per above discussion, the prototypical chain will be Foo -> Function.prototype -> Object.prototype
For option 2:
function Foo(){
this.name = 'bar';
}
Foo.prototype = { }
and the prototypical chain will be Foo -> Object.prototype
For both cases the prototypical chain is valid and inheritance works correctly without any doubt.
Any object can be a prototype. The prototype can be a plain old object, or a function or an array, which are both objects, or anything else which is an object, including regexps and even dates, not to mention objects wrapping primitives such as numbers and strings and booleans.
But when people talk about using, say, a function as a prototype, they usually intend, or hope, that they can somehow access that function from the instantiated object, but they can't. Instances look up properties on the prototype, whether it be an array or a Date or a regexp or a function or a plain old object, but they can't access the "body" of the prototype object, the thing which in the case of objects based on numbers or strings is called PrimitiveValue.
Here are some examples which might make it clearer, using the simplest case of creating an object based on a prototype with Object.create.
// plain old object prototype
prototype = { a: 42 };
obj = Object.create(prototype);
obj.a // 42
// array as prototype
array = [ 1, 2 ];
obj = Object.create(array);
array.a = 42
obj.a // 42
// NO WAY TO ACCESS [1, 2] from obj
regexp = /foo/;
regexp.a = 42
obj = Object.create(regexp)
obj.a // 42
// NO WAY TO ACCESS regexp from obj
> number = Object(22)
> number.a = 42
> obj = Object.create(number)
> obj.a // 42
// NO WAY TO ACCESS PRIMITIVE VALUE 22 FROM obj
Now let's consider the case of function as prototype. As with the other types of objects
fn = function() { };
fn.a = 42;
obj = Object.create(fn)
obj.a // 42
// NO WAY TO ACCESS fn from obj
However, since fn has its own prototype, including methods such as call, obj also inherits those. So obj.call is defined. However, calling it results in an error because obj is not a function that can be called.
> obj.call()
< Uncaught TypeError: obj is not a function
So the conclusion is that there's nothing particularly wrong or illegal with using a function as a prototype; there's simply no reason to.
Probably obvious, but still confusing me.
Is it in anyway possible to call from an another object's prototype a prototype inside another object?
Current set:
function obj1() {
this.myVar = 1;
}
obj1.prototype.helloWorld = function() {
alert("Hello world!");
}
function obj2() {
this.myVar = 2;
}
obj2.prototype.nonSense = function() {
console.log(this.myVar);
}
1. Can Obj2 prototype nonSense somehow call the prototype helloWorld in Obj1?**
2. Can Obj2 prototype nonSense somehow access the Obj1 variable myVar?
I'm not really sure what you're trying to do but you can call the helloWorld method directly:
obj1.prototype.helloWorld();
If you have an instance of obj1, you can get rid of the prototype:
var myObj1 = new obj1();
myObj1.helloWorld();
To access myVar from outside of obj1 you will need to have called obj1 - myVar won't exist until you have called the function in which it is declared. Most likely, you will want to create an instance of obj1 by calling it with the new operator, as shown above. You can then access myVar just like any other property:
console.log(myObj1.myVar);
var someObj = function() { }
var p = new someObj();
alert(someObj.prototype); // This works
alert(p.prototype); // UNDEFINED, but why?
someObj.prototype.model= "Nissan";
alert(p.model); // This works! I understand the dynamic nature of prototypes, but doesn't that mean that p.prototype === someObj.prototype?
Why is this so? Since "p" is an instance of "someObj", why is the prototype undefined? I mean, when I add a property to "someObj" prototype, it is accessible to "p", so why is the prototype not accessible?
The important thing here is that the prototype property of function objects is not the prototype of an object. It's the object that will be assigned as the prototype of an object you create via new someObj. Prior to ES5, you can't directly access the prototype of an object; as of ES5, you can, via Object.getPrototypeOf.
Re
alert(p.prototype); // UNDEFINED, but why?
The reason is that the p object doesn't have a property called "prototype". It has an underlying prototype, but that's not how you access it.
All function objects have a property called prototype so that if they're used as constructor functions, we can define what the properties of the underlying prototype of the objects created by those constructors will be. This may help:
function Foo() {
}
Foo.prototype.answer = 42;
console.log(Foo.prototype.answer); // "42"
var f = new Foo();
console.log(f.answer); // "42"
That last line works like this:
Get the f object.
Does f have its own property called "answer"?
No, does f have a prototype?
Yes, does the prototype have its own property called "answer"?
Yes, return the value of that property.
You've mentioned Object.create in the title of your question. It's important to understand that Object.create is quite separate from constructor functions. It was added to the language so that if you preferred not to use constructor functions, you didn't have to, but could still set the prototype of an object — directly, when you create that object.
That's because prototype is a property of the constructor function, not a property of itself. However, the prototype object has a reference to the constructor, so you can access an object's prototype via its constructor property:
function Foo() {}
Foo.prototype.foo = "bar";
var c = new Foo;
console.log( c.constructor === Foo ); // true
console.log( c.constructor.prototype ); // { foo: 'bar' }
However, this will not work if you overwrite the initial prototype property of the constructor function:
function Foo() {}
// I overwrite the prototype property, so I lose the initial reference
// to the constructor.
Foo.prototype = {
foo: "bar"
};
var c = new Foo;
console.log( c.constructor === Foo ); // false
console.log( c.constructor === Object ); // true
console.log( c.constructor.prototype ); // {}
That's why you're better off using the new Object.getPrototypeOf method introduced in ES5.
function Foo() {}
Foo.prototype = {
foo: "bar"
};
var c = new Foo;
console.log( c.constructor === Foo ); // false
console.log( c.constructor === Object ); // true
console.log( c.constructor.prototype ); // {}
console.log( Object.getPrototypeOf(c) ); // { foo: 'bar' }
Another solution would have been to make sure you restore the constructor reference on the prototype:
function Foo() {}
// Overwriting the initial prototype
Foo.prototype = {
constructor: Foo, // restore the constructor reference
foo: "bar"
};
p.prototype doesn't work because in this case p = someObj.prototype.
Basically when you use the new operator what happen is that the constructor someObj is used to initialize a new object. Which means it returns an object which have the properties and methods of the prototype of the constructor.
Thus p = someObj.prototype and p.prototype is undefined as p is not a constructor.
This article might help explains this more
http://www.htmlgoodies.com/html5/tutorials/javascript-prototypical-inheritance-explained.html#fbid=A2ikc3JLxeD
p is an instance of someObj. The prototype belongs to the constructor. You can retrieve p's constructor prototype using p.constructor.prototype
In Javascript, constructors, and in fact all functions get a prototype property. An objects (that is, a set of key-value pairs), does not have a prototype property. In your example above,
var someObj = function() { } // this is a function, so it has a prototype property
var p = new someObj(); // this is an instance object, so it doesn't
That's why someObj.prototype is defined, but p.prototype is not.