How are functions stored in a variable?
According to MDN
In JavaScript, functions are first-class objects, because they can have properties and methods just like any other object. What distinguishes them from other objects is that functions can be called. In brief, they are Function objects.
Suppose this scenario,
var fn = function () {};
fn.attr = 3;
console.log(fn); //prints function() {}
console.log(Object.keys(fn)); //prints ["attr"]
If a function is an object shouldn't it have keys and value kind where the function is stored in a property and the interpreters don't show that property? Something like C++ style operator overloading or array/object representation in Javascript itself. I mean to say are functions (or arrays) are just objects treated in a different manner? Which might imply that anonymous functions are stored in an object with a hidden property.
In summary, what is the underlying working of functions(or arrays)? Are they treated specially? Or are they just syntactic sugar for some hidden property which is called when () is used?
Yes, functions are special.
Proof
const f = Object.create(Function.prototype);
f(); // TypeError: f is not a function
Exposition
They are "callable objects" that can only be created via prescribed syntax (function expressions, statements, declarations, fat-arrows, object literal method definition shorthand, Function constructor, class methods).
That means they have a special [[Call]] method (not visible to you) that is called when you invoke them with the () syntax.
[[Call]] coordinates:
the creation of the execution context (call-stack frame)
addition of the new execution context to the top of the stack
execution of the function logic
removal of the execution context from the stack
cueing up the next context to run (the one immediately lower on the stack)
supplying any return value to the next execution context
Creation of the execution context in turn completes configuration of the LexicalEnvironment (used for scoping), configuration of the receiver (this) for the function and other meta-logic.
Functions also differ from most normal objects in that they have Function.prototype on their [[Prototype]] chain (although you can create your own 'useless' object by inheriting from Function.prototype - see above).
For a full list of differences, please see MDN, the spec etc.
Related
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
I took a look at one of the rules from eslint-plugin-security and found that user input could in theory lead to a Remote Code Execution bug.
const a = class {};
console.log(a['constructor']);
a['constructor']('console.log(1)')();
function b() {}
console.log(b['constructor']);
b['constructor']('console.log(2)')();
const c = {}
console.log(c['constructor'])
console.log(c['constructor']('console.log(3)')());
From the snippet it's easy to see that constructors of classes and functions seem to parse strings and evaluate them as valid code. Objects for some reason don't exhibit this behaviour.
Why is this even allowed to happen? What feature of JavaScript needs this behaviour from function/class constructors? I'm assuming it's integral to the way JavaScript works otherwise I don't see why it hasn't been removed from the language.
The problem is that the .constructor of a class is Function, and calling the Function constructor with a string creates a function from that string, and then calling that function results in the string's code being executed:
const a = class {};
console.dir(a['constructor'] === Function);
a['constructor']('console.log(1)')();
This isn't really any different from
Function('console.log(1)')();
It's just that a class's constructor property happens to point to the same thing.
Objects can exhibit the same property, if you navigate up to the .constructor property twice (first one accesses the Object constructor, second accesses the Function constructor):
const a = {};
console.dir(a['constructor'].constructor === Function);
a['constructor'].constructor('console.log(1)')();
If you allow arbitrary access to properties of any object, and also allow those properties to be called with arbitrary arguments, pretty much anything can be executed. The prototype chain (and .constructor) properties are useful, but like many things, they can be misused.
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 have been going through Javascript Koans when I hit upon the part about inheritance. I became deeply fascinated and spent the entire morning researching how inheritance works in JS.
I understand that a function can be used to execute code which is declared in its code body, and a function can also serve the purpose as a constructor for objects which inherent from that functions prototype object.
It seems as though functions have two purposes that are not at all related- the ability to create objects, and the ability to execute it's declared code. Is there any relationship between these two abilities?
An attempt at a simple answer (with some approximations to try and keep it simple)
You could see a "class" function both as the constructor of the underlying object and the place where its methods are defined.
Construction
The new operator will create an empty object whose type will reference the function and bind it to this, then call the function.
The function may set some properties of this, which will become values for the new instance properties.
Methods
In JavaScript almost everything, notably functions, can have properties.
Among these, the conventionally named prototype property is the container of all class methods (and possibly other property values).
function Guy (name) { this.name = name; }
Guy.prototype = {
sayHello: function () { console.log ("Hello, I'm "+this.name; }
}
the Guy method sayHello is literally the property Guy.prototype.sayHello, which happens to be a function.
You could just as well add values instead of functions to the prototype property, which would act as class variables (of sorts).
So let's create an object Bob from the function/class Guy:
var Bob = new Guy("Bob");
Bob.sayHello();
when you invoke Bob.sayHello(), the virtual machine will first look for a Bob.sayHello property (which usually does not exist), then for a Guy.prototype.sayHello (and would go up the inheritance chain or die trying, but that's another subject), then bind this to Bob and call Guy.prototype.sayHello, which will be able to access the Bob instance through this.
As an illustration of the mechanism, you can break the prototype chain for a given object instance:
Bob.sayHello = function () { console.log ("my real name is Robert"); }
The duality you're describing doesn't in fact exist. Functions exist to be executed. But, in JavaScript, functions are also objects, so they can have properties such as prototype. (You can add other properties to your function and use them from its body as a means of making it "stateful".) From the function's point of view, prototype is just another ordinary property.
Object construction is the domain of the new operator. What it does, is this:
it creates an empty object,
it creates a hidden, non-modifiable binding between the created object and its constructor, which is then used to look-up a property value on its prototype whenever a property doesn't exist on the object itself,
it executes the provided function in context of that object (this points to it during that function's execution), and
it returns either the created object (if the provided function returned undefined) or the return value of the provided function.
(The {} notation for creating objects is just a shortcut for new Object().)
Additional note on prototypal inheritance (that is used in JavaScript): The second step in the above sequence has an important result. Any object in JavaScript has a constructor ({} has Object as constructor), so setting an object as the value of prototype property of your function doesn't just create a single binding. It transitively creates a "prototype chain". Any property is then looked up first on the object, then on its constructor's prototype, then on it's constructor's prototype's constructor's prototype, etc.
I've been reading the book named "Object Oriented Javascript" by Stoyan Stefanov. I see this sentence:
function is actually an object that is built with 'Function' constructor function (with capital F).
The author demonstrates this with some nice examples. However, based on that statement, I got this question that can't be answer by myself. As 'Function' constructor is a function, so 'Function' function is an Object, then 'Function' object needs another constructor function to build it and that another constructor function is again an Object (because it's a function).
Well, I end up with this endless logic. Can someone help me point out the wrong point in my thinking?
'Function' function is an Object, then 'Function' object needs another constructor function to build it
No. Function is a native, builtin object whose properties and behavior are defined in section 15.3 of the EcmaScript specification. It was not built by an js function.
Think of it like that: There is a function somewhere in the code of your EcmaScript environment that builds function objects - it is called whenever your script encounters a function expression or declaration. The global Function function is a wrapper for that function to make it accessible for scripts. All function objects which that function returns inherit from the Function.prototype object - it looks like they were constructed by Function. Also the Function.prototype.constructor property that all functions inherit is defined to point to Function.
A function in JS embeds 2 concepts:
An entity
A functionality
A function entity is some sort of "capsule" that contains a functionality, i.e., the power of transforming several inputs into an output. This capsule is what we know as "object". At the end of this recursion you find the identity Function.constructor === Function, which sets the limits of the introspective features of the language. The rest of JS functionalities cannot be accessible by the language itself because there not exists any capsule or object that embeds them.
In JS you cannot define standalone 'functionalities' but you create objects that implement such functionalities that can be treated as any other objects. The Function object is the core object for implementing functionalitites. Either if you define named or anonymous functions (by means of the function keyword) you are creating a Function object that is bound either to a name (for named functions) or directly to a variable (unnamed functions).
function foo(a, b) { return a+b; } //This function is a Function object bound to the name `foo`
var a = function(a, b) { return a+b; } //the Function object is bound to `a`
In the same manner the Array object has the [] operator, which is used to access to array elements, you may interpret () as an operator of the Function object which is used for invoking its embedded functionality.