So as long as anything in Javascript is actually an object, what makes an object behave as a function? What internal properties and labels make an object behave as an object we can call instead of just using it to store values?
There is an internal property, [[Call]], that determines what will be executed, when the object is called.
Plain objects don't have this interal property, so they aren't callable, and can't be made to be callable.
The only callables in JS are functions (which are also objects), classes (which are actually functions, and therefore objects as well), and Proxy objects that wrap callables.
To create a callable object, create a function, and make it have the properties and prototypes you would like.
So as long as anything in javascript is actually an object
Well, not everything in JavaScript is an object. For instance, primitives such as strings, booleans and numbers are not objects. JavaScript just wraps these primitives in objects when properties are accessed.
what makes an object behave as a function what internal properties and
labels did this job to make an object behave as an execution code
instead of just storing variables
You're correct about functions being objects, however, unlike regular objects which just store key-value pairs, function objects have a special internal method which they implement known as [[Call]]. This call method is what executes the code associated with the function object and is invoked when you call a function (func_name()). So, any object which implements the internal [[Call]] method is callable. You yourself cannot make an object callable by implementing this property as it is not part of the ECMAScript language itself, but rather a method name used by the spec. Instead, we use the function keyword for that. Function objects are still objects at the end of the day, so you can assign properties to them as well as access preexisting properties:
function foo(a) {
return a;
}
foo.bar = "foobar";
console.log(foo.length); // able to access pre-existing properties
console.log(foo.bar); // able to access our own properties
console.log(foo(2)); // able to invoke (due to [[Call]])
You can read more about function objects here
You could assign an object to a function to get a callable function.
var object = { foo: 42 },
callable = Object.assign(function () {}, object);
console.log(callable)
console.log(callable())
console.log(Object.keys(callable));
You can't make an object callable.
You can add properties to an already existing Function object though. You will still retain call() behavior, but can also get and set properties.
var object = { increment: function(x){
return x+1
} ,
foo: 'foo'
};
var decrement = function(x){
return x-1
}
callable = Object.assign(decrement, object);
console.log(callable.increment(12)) //13
console.log(callable(67)) //66
console.log(Object.keys(callable));//[ 'increment', 'foo' ]
There are different prototypes in javascript. E.g. Object.prototype, Function.prototype, Array.prototype. Javsacript works based on prototypical inheritance. This defines what is the type of any object.
When you create a function, its __proto__ (also called as "dunder proto") is set to Function.prototype. Basically a function inherits from Function.prototype which in turn inherits from Object.prototype. Following example is taken from MDN. (Note - I think __proto__ is not standardized. Object.getPrototypeOf should be used)
function f() {
return 2;
}
// Functions inherit from Function.prototype
// (which has methods call, bind, etc.)
// f ---> Function.prototype ---> Object.prototype ---> null
MDN has a great explanation for prototypical inheritance. For more information read this https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
Related
I need some help for understanding the prototype chain. I don't understand / not quite sure if my assumptions are correct. I want to understand the link to the Object.prototype.
One example
function A(){};
var newObject=new A();
I know the newObject has an internal property [[prototype]] which has a reference to A.prototype.
And this prototype-Object has also an internal property with reference to Object.prototype, right?
But why does it have that reference? Is it because the prototype of A (used as constructor) is an object which can be imagined to be created by A.prototype=new Object() ( which will be done automatically in the background). And now I have a reference to the prototype of Object?
I hope I explained it clearly.
Please let me know your comments.
Many thanks
Yes, your understanding is correct.
In JS, pretty much all the objects have a reference to Object.prototype in their prototype chain.
The [[Prototype]] of an object refers to Object.prototype as the end of a prototype chain. In your example, this means what you described:
[[Prototype]] [[Prototype]]
newObject -----------------> A.prototype -----------------> Object.prototype
That applies to...
objects created by the Object constructor (i.e. new Object(...)),
those created with an object literal (which you can think of as syntax sugar for a new Object() call followed by a bunch of Object.defineProperty calls) and
objects created internally by the JS interpreter (like A.prototype which is created automatically when you define the A function).
There are also exceptions of this "rule" though:
Object.prototype itself.
If it had a reference to... well, itself, it would create and infinite recursion when a nonexistent property is looked up. Hence, it has no prototype, which means that its [[Prototype]] is null (that's how a prototype chain "ends").
Custom objects created using Object.create or modified with Object.setPrototype.
The [[Prototype]] can be set to anything this way, including null or other objects whose prototype chain doesn't end with Object.prototype.
This is indeed what the ECMAScript specification prescribes. When a function is defined with the function keyword, then an object is created from Object.prototype which is assigned to the function's prototype property, and therefor will be used as prototype for any object that is constructed by that function.
This specification can be found at Make Constructor, step 5.a:
5.a. Set prototype to OrdinaryObjectCreate(%Object.prototype%).
When it comes to javascript every value is either an object (arrays, objects, sets, maps...) or a primitive(Numbers, strings, bool ...) objects and primitives are the two data types in javascript a . You have the Number, String , Array and even Object constructors which you can use to create the corresponding value.
And when you create new object using the new operator the following steps happen consecutively:
// 1. New empty object is created
// 2. the constructor function is called, and the this keyword is assigned to the empty object i.e this = {}.
// 3. the empty object is linked to the prototype of the constructor functio i.e {}.proto = constructorFunction.prototype.
// 4. the constructor function automatically return the new object {}.
keep in mind that constructorFunction.prototype is the prototype of the new object that is created from the constructorFunction and not of itself.
I hope this clears things up a little for you!
But why does it have that reference?
To answer in one sentence - because prototype is an object itself and has its own prototype. When you create function in JavaScript it has a property called prototype. When you use that function as a constructor function (with new operator), new object is creating which as you wrote is linked to its constructor function prototype via internal [[prorotype]] property. That prototype object is plain JavaScript object which [[prototype]] property references Object.prototype.
Consider this code:
function foo(something) {
this.a = something;
}
var obj1 = {};
var bar = foo.bind(obj1);
Now the following statement doesn't execute:
bar.prototype.newprop = "new"; // Cannot execute this
As I understood, every function has a prototype object. Then why can't we execute the above statement?
And bar is indeed a function as we can call it:
bar(2);
console.log(obj1.a); // 2
As I understood, every function has a prototype object.
Well, there are exceptions to every rule :-) You found one: bound functions don't have a .prototype property because they don't need it. When you call a bound function with new, it calls the original function as a constructor, using the original's .prototype object as the prototype of the new instance.
In fact, since ECMAScript 6 many functions don't have a .prototype property with an object, because they are not constructors - they cannot be called with new so they don't need it. Among those are
arrow functions (() => {…})
methods (method() { … } in object literals and classes)
builtin non-constructor functions (like Math.sin)
See the specification:
Function.prototype.bind ( thisArg , ...args)
[...]
NOTE 1 Function objects created using Function.prototype.bind are exotic objects. They also do not have a prototype property.
The returned function from .bind() has no prototype object. You can give it one:
bar.prototype = { newprop: "new" };
It is not true that "every function has a prototype object". Every function can have a prototype object, but the value of the "prototype" property can be anything, including null or undefined.
Additionally, there are "special" functions that may not behave like ordinary functions in all cases.
Adding properties to the prototype means you want to create an object by using the function as a constructor.
When you create an object like by calling new on a function, the this value is the new object being created. So it makes no sense to bind this to another value.
When you do a "typeof" on both of these types you get "function" for functions and "object" for objects, but isn't it so that functions are special objects, if so what are the properties that differentiate a function from an object?
When you do a "typeof" on both of these types you get "function" for functions and "object" for objects,
First of all, the specification for typeof is basically just a lookup table, where it says "if the value is a function object, return the string "function"). So it doesn't provide the real data type of the value (which would be object for functions).
but isn't it so that functions are special objects
Yes. Functions are so called callable objects.
Objects have, in addition to "normal" properties, so called "internal" properties. You can think of these as some kind of internal state, that needs to be maintained for the object to work correctly, but that is not accessible in user code.
Some of these internal properties make certain objects special because not every object has them. One of them is [[Call]] (internal properties are denoted with double brackets), which contains code in some implementation-specific format.
When you call a value (i.e. foo()) the interpreter first checks whether the value is an object and then checks whether it has an intern [[Call]] property. If yes, then the code stored in that property is executed.
Here is a very rough example of how this could look like internally:
// Simulates a function call implementation, i.e. what happens when
// you do `foo()`
function call(value) {
if (typeof value !== "object") {
throw new Error('Not an object');
}
if (!value["[[Call]]"]) {
throw new Error('Not a function');
}
return eval(value["[[Call]]"]);
}
// Simulated function object that has a name ("normal" property)
// and the internal property [[Call]].
// This would be the internal representation for something like
// function func() {
// console.log('some code');
// }
var func = {
name: "func",
"[[Call]]": "console.log('I\\'m a function!');",
};
call(func);
Side note: If you know Python, then this concept should be familiar to you, because Python allows you to make arbitrary objects callable by implementing __call__.
In addition to [[Call]] there is also [[Construct]]. We actually distinguish between callable and constructable functions. Constructable functions are those that can be invoked with new. Functions created via function ... are both callable and constructable. Arrow functions are only callable, functions created via class ... are only constructable. And this distinction is made based on whether [[Call]] or [[Construct]] or both are set.
if so what are the properties that differentiate a function from an object
In addition to these special internal properties, function objects also have all properties defined on Function.prototype:
console.dir(Function.prototype);
// etc
(and Function.prototype "extends" Object.prototype) which is where .call and .apply are defined, but these alone do not make functions special. The internal [[Call]] property is what makes them special.
The same applies to other built-in "classes" such as Array, Date or RegExp. All instances of these classes have additional methods/properties that are defined on Array.prototype, Date.prototype, etc.
Functions (which are first-class objects) can be called, while other objects cannot.
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions for more detail.
I found this picture here
In this case, foo is a constructor function and B and C are objects. I am very confused, first off when you create an object does it always come with the properties and proto? Is that the default? Also in terms of the constructor function for foo. Am I correct to say that every proto of a function defaults to Function.prototype, which uses Object.prototype to create an object? The part that is confusing for me is Foo.prototype, when was this prototype created? Does a constructor function always default to the creation of a prototype which a constructor reference set back to itself and a proto set to object?
No wonder there is confusion. The picture is misleading to the point of being incorrect!
Objects created by calling a constructor function with the new keyword have their inheritance chain set to start with the prototype property of the constructor (correct in the picture).
The prototype property is created every time a function is declared using the function keyword to cover the case of the function being use as a constructor later - so you don't need to specify if a function is a constructor or not. For completeness, functions generated by the class keyword also have a prototype property.)
The function's prototype property's constructor property is set to the function when the prototype property is created (meaning when the function is declared). Again the picture is correct: the value of Foo.prototype.constructor is a reference to Foo.
What is wrong in the picture is objects a and b somehow joining together in a reverse fork and their properties becoming available to instances of Foo.
constructor is always an inherited property. If you replace the original prototype property of a function object with another object, you replace the constructor property inherited by objects constructed with the function. Although you can reset the constructor property of a functions prototype property, it's reasonably unusual and not a part of the story the picture is presenting.
If you do modify the inheritance chain by changing a function's prototype property value, the inheritance chain is still always a single threaded chain back to Object.prototype and then null. The inheritance chain never forks as shown in the picture. If you modified Foo.prototype in the picture to make it a or b, the constructor property of Foo instances would not be Foo.
The picture requires a lot of explanation to be useful.
The properties are assigned in the construction function. Any function can be used with new,thus becoming the "construction function".
var f = function(){};
var fInstance = new f();
console.log(fInstance.constructor); // *f*
If there are no properties assigned in that function (using this.propertyName), then the constructed instance will not have properties. If it does, then it will.
// No properties
var f = function(){};
// Two constructor properties, and one default property
var f = function(prop1, prop2){
this.name = prop1;
this.description = prop2;
this.something = "default";
};
If the prototype of the construction function has properties or methods (basically just glorified properties) attached to its prototype, then each instance will have those.
// No prototype
var f = function(){};
// Prototype with one method
var f = function(){};
f.prototype.test = function(){ console.log("hello"); };
The prototypes and properties must be manually created, and may or may not exist. By default, since using new requires a function, there will always be a constructor function. The process of instantiation using new will also always assign the prototype of the constructor to an object containing the constructing function as a property named constructor as well as all of the properties/methods of the construction function's prototype.
In this case, foo is a constructor function and B and C are objects.
Functions are also objects. Everything are objects. unlike classical inheritance where what defined objects are separate entities. Here an object that is an instance of Function is the constructor that will create an instance of its kind that inherits whatever object is on the constructors prototype attribute.
I am very confused, first off when you create an object does it
always come with the properties and proto? Is that the default?
Only way to get the objects own property y is if the constructor function sets this.y. If a property is not found on the object the system will continue to look at the object that was on the constructors prototype field. Some implementations has this as __proto__ but that is not a requirement. It is implementation specific how it is stored on the instance.
Also in terms of the constructor function for foo. Am I correct to say
that every proto of a function defaults to Function.prototype, which
uses Object.prototype to create an object?
function() {...} makes an instance of the constructor Function. All objects except Object itself inherits Object either indirectly or directly, including Function. Basically you can make a function like this:
var f = new Function('a', 'b', 'return a + b');
f is an instance of Function, as you can see. This is almost the same as:
var f = function(a, b) { return a + b; };
Now the first allows for text to be interpreted as code so its less efficient, but I imagine that in the early days these two would be identical in terms of interpretation. Modern engines prefer the last one since it is more predictable while the first can be seen as a specialized eval.
The part that is confusing for me is Foo.prototype, when was this
prototype created? Does a constructor function always default to the
creation of a prototype which a constructor reference set back to
itself and a proto set to object?
Yes. When the function Foo is created, JS creates by default protoype as new Object(), then it sets constructor to itself. The rest needs to be done in the code itself so we know there is something like this after the actual function code to do the rest of the class:
Foo.prototype.x = 10;
Foo.prototype.calculate = function(...) {...};
The following snippet of code is taken from Eloquent JavaScript.
var noCatsAtAll = {};
if ("constructor" in noCatsAtAll)
console.log("Yes, there definitely is a cat called 'constructor'.");
I find it quite mystifying. Why does the 'if' return true?
JavaScript objects have a function called constructor which is the function that created the object's instance. It's built-in to all objects. The in operator tests for the presence of something called "constructor" in the instance of your dictionary, so it returns true. The same thing would happen if you tested for length, for example.
All instances of Object have a constructor property that specifies the function that constructs the Object's prototype.
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object#Properties_2
The in operator looks at all properties, including inherited ones. If you only want to see the properties on the object itself, you can use hasOwnProperty:
var a = {};
"constructor" in a; // true
a.hasOwnProperty("constructor"); // false
Note that while the in operator sees "constructor", a for (key in a) loop wouldn't. This is because the "constructor" property is non-enumerable.
It is the constructor of the Object type. A reference to the constructor function is available directly on that property ("constructor") of an object (it applies to constructors you write too).
In turn, the names of properties present are in objects.
constructor is a method of Object. You can find the constructor method throughout all objects unless you modify it. The in operator will find methods through the prototype chains. Which is is why it's recommended to use hasOwnProperty to test for properties in your own objects.
var noCatsAtAll = {};
if ("constructor" in noCatsAtAll)
console.log("Yes, there definitely is a cat called 'constructor'.");
if ('constructor' in Object)
console.log("Yes, there is also a method called constructor");
var noCon = Object.create(null); // create a completetly empty object
console.log('constructor' in noCon); // false
function hasConstructorToo() {}
console.log('constructor' in hasConstructorToo) // true
console.log('constructor' in []); // true
http://jsfiddle.net/Xsb3E/3`