According to this, functions inherit from Function and Function from Function.prototype in turn:
The global Function object has no methods or properties of its own, however, since it is a function itself it does inherit some methods and properties through the prototype chain from Function.prototype.
What's the point of Function.prototype then? Why not move its properties to Function and let Function.prototype be undefined? Functions would be derived from Function instead.
Same goes for Object etc.
functions inherit from Function
You are quoting MDN loosely. What it actually says is:
function objects inherit from Function.prototype
Note that on the MDN page, the initial word "function" in the above sentence is capitalized, but only because it is at the beginning of the sentence, not because it is referring to the JS object Function. It is referring to regular old functions declared as function() { }.
Remember that MDN is written by mere mortals. I would prefer they did not use the words "inherit" and "inheritance", not to mention "derived". JS does not have the concept of inheritance in the strict sense of the word. If you use this terminology, you will end up confusing yourself. What JS has is prototypes associated with objects. When accessing a property on an object, if it is not found, the prototype is consulted. If not found there, since a prototype is also an object with a prototype, the prototype's prototype is consulted, and so on up the chain.
Therefore, the above sentence would better be written as "function objects have as their prototype Function.prototype".
The JS Function object is not directly associated with Function.prototype, other than the fact that Function.prototype is a property of Function, and, since the Function object is itself a function, it itself has Function.prototype as its prototype. Whatever properties may or may not be present on Function, or hung on it by you, have nothing to do with the prototype chain and are not "inherited" by anyone.
When you do (function() { }).call(), the call property/method is first looked up on the function object itself; if it does not exist there, as it normally would not, then it is looked up on the prototype assigned intrinsically when the function was declared, which is Function.prototype. Where else would you put methods such as call or apply if not on Function.prototype? What else would you call the prototype automatically assigned to functions other than Function.prototype?
As an aside, note that Function.call will resolve correctly to the internal call function. Why? Not because that is where call lives, or because that is from where regular functions "inherit" call, but rather because, since as I mentioned before, Function is itself a function, and therefore has the prototype Function.prototype, call can be found on its prototype chain.
What's the point of Function.prototype then? Why not move its properties to Function and let Function.prototype be undefined? Functions would be derived from Function instead.
X.prototype is a property on X used as the prototype for objects created using X as a constructor. Therefore, to assign the correct prototype to objects created using Function as a constructor (which includes functions declared as function x() { }), the prototype must be present as the prototype property on Function.
Functions on the prototype are only created once and shared between each instance. Functions created in the constructor are created as new objects for each new object created with the constructor.
As a general rule functions should be on the prototype since they will generally not be modified for different objects of the same type, and this has a slight memory/performance benefit. Other properties like objects and arrays should be defined in the constructor, unless you want to create a shared, static property, in which case you should use the prototype.
Its easier to see the distinctions with normal objects or arrays rather than functions
function Foo(){
this.bar = [];
}
var fooObj1 = new Foo();
var fooObj2 = new Foo();
fooObj1.bar.push("x");
alert(fooObj2.bar) //[]
as opposed to:
function Foo(){
}
Foo.prototype.bar = []
var fooObj1 = new Foo();
var fooObj2 = new Foo();
fooObj1.bar.push("x");
alert(fooObj2.bar) //["x"]
You need Function.prototype for if you want to extend functions, consider this:
Function.prototype.moo = 5;
function x() { };
console.log(x.moo); // 5
every function you make now has the property moo, versus:
Function.quack = 6;
function b() {};
console.log(b.quack); // undefined
This is not true if you just slap a property onto Function. Every function DOES NOT inherit properties assigned to Function, which is why you need Function.prototype.
Related
In Javascript, functions are objects. Yet typeof of a function returns function instead of object for ECMAScript compatibility reasons.
Is this function type actually some kind of wrapper for object that can be determined somehow? Or in Javascript, is a function actually fundamentally different from objects?
I do understand that functions are effectively and practically objects. But are they by definition actually completely separate from Objects in Javascript, or is there a way to programmatically reveal the Object that the Function is made of?
As the spec says:
an object is a member of the built-in type Object; and a function is a callable object
So
Or in Javascript, is a function actually fundamentally different from objects?
Not really, except for the fact that a function is callable - more precisely, that it has a [[Call]] internal method.
Functions inherit from objects in a very similar way that objects inherit from objects. For example, for a given function:
function foo(){}
foo.a = 'a';
There is:
The foo function, which is an object, and has a [[Call]] internal method, as well as an a property, and a few other properties that functions have (like name)
The foo function inherits from Function.prototype
Function.prototype inherits from Object.prototype
Object.prototype inherits from nothing - that's the start of the prototype chain
is there a way to programmatically reveal the Object that the Function is made of?
That's not really how it is - the function itself is an object. If the function object has properties, it'll be visible directly on the function. For example, above, referencing foo.a will give you the string 'a'. The a property isn't separate from the function - it's directly on the function object.
I am reading through the official docs:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
and in the chapter Different ways to create objects and the resulting prototype chain -> With a constructor they have the following:
function Graph() {
this.vertices = [];
this.edges = [];
}
Graph.prototype = {
addVertex: function(v) {
this.vertices.push(v);
}
};
var g = new Graph();
// g is an object with own properties 'vertices' and 'edges'.
// g.[[Prototype]] is the value of Graph.prototype when new Graph() is executed.
But right before that it is written that:
// Functions inherit from Function.prototype
// (which has methods call, bind, etc.)
// f ---> Function.prototype ---> Object.prototype ---> null
So, Graph is a function and it should have Graph.prototype, in my understanding, to be of type Function.prototype and NOT Object.prototype, otherwise Graph would stop being a function and would instead become an object, or so I would think.
Could anyone explain why the prototype of Graph is assigned to an object and why the specified behavior of inheriting then addVertex becomes possible? Would we lose all of the function properties (call, bind) when such assignment happens?
There are two different prototype chains at play:
The prototype chain of the constructor
The prototype chain of objects that are created by that constructor
They have nothing to do with each other. The first is a function and thus related to Function.prototype, the other is not a function, but an object whose prototype object is created at the same time as the constructor function object was created. That prototype object will be used when a new instance is created by calling the constructor with new.
What can be confusing here, is that the constructor has a property that is called prototype, but that is not the prototype object of the constructor (point 1), but of objects it can create (point 2). Possibly this property would have been better named prototypeForConstructedInstances... but that's a bit long ;-)
To get the constructors own prototype you would write Object.getPrototypeOf(constructor),... and you'll see it is Function.prototype.
You may have an interest in reading more about the broader subject of prototypes at "How does JavaScript .prototype work?". It's an interesting read, and you'll also find my answer over there.
If we create a function like:
function Rabbit() {}
We see that it inherits from the same object that Function inherits from i.e.
Rabbit.__proto__ === Function.__proto__
What is this higher object? If we try to log it it looks like : ƒ () { [native code] }. Shouldn't Rabbit be inheriting from Function object because it's a function? Can somebody explain where i'm wrong?
What is this higher object?
It's the object referenced by Function.prototype, which is also a function. It's where functions get their properties and methods from (call, apply, bind, name, and length).
That object's prototype is the object referenced by Object.prototype, which is responsible for basic object properties and methods such as hasOwnProperty and toString and, since you used it in your example, __proto__ (which is a web-only feature for backward compatibility; don't use it, use Object.getPrototypeOf instead).
Shouldn't Rabbit be inheriting from Function object because it's a function?
No, that's what Function.prototype is for.
Let's put Function, specifically, aside for a moment. Suppose you have:
function Thingy() {
}
and
let t = new Thingy();
Object.getPrototypeof(t) === Thingy.prototype will be true, because when you use new Thingy, the resulting object gets the object that Thingy.prototype points to as its prototype. This is how constructor functions and prototypes work in JavaScript.
Function is a constructor that creates functions. So the equivalent would be:
let Rabbit = new Function();
Object.getPrototypeOf(Rabbit) === Function.prototype is true. It's also true for functions that, like your Rabbit, aren't created via new Function.
Shouldn't Rabbit be inheriting from Function object because it's a function?
No, because it is a regular function. Every function you create this way is actually a Function object instance. See mdn.
In order to make a Function be a prototype of your object you need to explicitly specify it as a prototype of your object and create an instance using new keyword.
I am reading JavaScript: Good parts by Douglas Crockford. I came across this following useful trick.
Function.prototype.method = function (name, func) {
if (!this.prototype[name]) {
this.prototype[name] = func;
}
};
Based on the above code snippet, what I understood is, as all functions are objects of Function and as the above function adds the 'method' method to prototype of Function, there will be a method method available on all functions.
var pfun = function(name){
this.name = name;
};
Consider the following log statements
console.log(Function.prototype.isPrototypeOf(pfun));//true - Thats fine
console.log(pfun.prototype == Function.prototype);//false - why?
I couldn't understand why the above logs contradict each other.
Here pfun is a functions which has the method method available from its prototype. So I can call the following.
pfun.method("greet",function(){
console.log(this.name);
});
Now as method method runs, it adds the greet method to pfun's prototype. If the above logs doesn't contradict each other, then greet method should be available to all functions.
My question is, why the above logs are contradicting each other?
isPrototypeOf checks to see if an object is referenced by the internal [[Prototype]] property of another object.
All ECMAScript native functions inherit from Function.prototype therefore:
Function.prototype.isPrototypeOf(pfun))
returns true.
Every native function created by the Function constructor has a default public prototype property that is a plain object (see ECMAScript §13.2 #16). So when you do:
pfun.prototype == Function.prototype
you are comparing this plain object to Function.prototype1, which are different objects.
This confusion is brought about in discussion because the public and private prototype properties are often only distinguished by the context in which the term is used. All native Functions have both, and only for the Function constructor are they the same object by default, i.e.
Object.getPrototypeOf(Function) === Function.prototype
returns true. This relationship can be established for other Objects, but it doesn't happen by default (and I can't think of an example or sensible reason to do it).
1 The Function.prototype object is a bit of an oddity. It has an internal [[Class]] value of "function" and is callable, so in that regard it's a function. However, its internal [[Prototype]] is Object.prototype, so it can probably be called an instance of Object. When called, it ignores all arguments and returns undefined.
They don't contradict each other. Your pfun has a prototypal inheritance from Function, but it's not a reference to Function's prototype. It has its own prototype (that is derived from Function's one).
So, when you ask if Function.prototype.isPrototypeOf(pfun), you get true, because pfun's prototype is derived from Function's one. But when you ask if pfun.prototype is equal to Function.prototype, you get false, because it's false, pfun has its own prototype.
The method greet is added only to the pfun's prototype, and not to the Function's one.
But if you do:
Function.prototype.method('greet', function() {
console.log(this.name);
});
Then, all the function's prototypes (that will be derived from Function.prototype) will have the greet method in its prototype, because of the prototypal inheritance.
I am new to JavaScript and I am following Douglas Crockford's book, The Good Parts.
It says:
Every function object is also created with a prototype property. Its value is an object with a constructor property whose value is the function. This is distinct from the hidden link to Function.prototype.
I understand that function objects are linked to Function.prototype, but what does the above line mean?
Can someone simplify it for me?
Every function object is also created with a prototype property.
var fn = function() { };
fn.hasOwnProperty("prototype"); // true
That is, for every function in JavaScript, each one has a prototype property, just like any other JavaScript object.
Its value is an object with a constructor property whose value is the function.
The object that prototype points to has a constructor property which points to the original function.
fn.prototype.constructor === fn // true;
That is, you can derive the constructor function from a constructed object by looking at obj.prototype.constructor (unless it's been overwritten).
This is distinct from the hidden link to Function.prototype
The function you create's prototype object is not the same as the Function's prototype.
fn.prototype != Function.prototype // true
That is, if you augment Function.prototype, then the methods will be available on function references. If you augment your function's prototype, then those methods will be available on constructed objects using that constructor.