If functions are objects, then where does the function body go?

If functions are objects, where is the body of the go function?

Let me clarify what I am confused about. Functions are objects, everything is fine. I can think of an object as a hashmap made up of string keys and arbitrarily typed values. I can do it:

function Square(size) {
    Rectangle.call(this, size, size);
}
Square.prototype = new Rectangle();

      

I just treated it Square

as a normal object and confused it with a property prototype

by assigning a new value to it. However, if functions are just objects (or hash maps, for that matter), where is the body of the function stored (in this example Rectangle.call(this, size, size);

)?

I figured it should be stored as the value of some property, like the following:

console.log(Square.executableBody); // "Rectangle.call(this, size, size);"

      

This is obviously not the case. Interestingly, while reading "Principles of Object Oriented JavaScript" by Nikolai K. Zakas, I came across this:

[...] functions are actually objects in JavaScript. The defining characteristic of a function — what distinguishes it from any other object — is the presence of an internal property named [[Call]]. Internal properties are not available via code [...] The [[Call]] property is unique to functions and indicates that the object can be executed.

This might be the property I was looking for above. However, this does not go into detail. Is the body of the function actually stored in a property [[Call]]

? If so, how does execution work? Unfortunately I was not able to find out more about [[Call]]

, Google basically came up with information about the function method call

...

Some clarification would be much appreciated! :)

+3


source to share


2 answers


It becomes the value of another internal property called [[Code]]

:

13.2 Creating Function Objects
Given the optional parameter list specified by the FormalParameterList, the body specified by the FunctionBody , the lexical environment specified by the scope, and the Boolean Strict flag, a Function object is constructed as follows:

[...]

  1. Set an internal property [[Code]]

    for F in FunctionBody.



If so, how does execution work?

The function call basically calls an internal method [[Call]]

which is described at http://es5.github.io/#x13.2.1 . I think an important step:

  1. Let the result be the result FunctionBody assessment is the value of the internal properties of the F [[Code]]

    .
+4


source


Basically, for all practical purposes, you can treat the entire function as an object. You can look into the source code of the JS spec or JS to see how the body of the function is actually stored in an internal property of the object, but that will not help you understand how it works as a JS programmer. You can see the body as a string when evaluating fn.toString

. You cannot access the body in any other way, except to execute it or associate with it, or call other methods on Function.prototype

. However, since it is an object, it can also have properties attached to it like any other object.

Why would I want to bind a property to a function? Here is an example memoization function (intentionally simplified):

function memoize(fn) {
    var cache = {};
    function memoized(x) {
        return x in cache ? cache[x] : cache[x] = fn(x);
    };
    memoized.clear = function() { cache = {}; };
    return memoized;
 }

      

So, we put the function clear

as a property of the returned function. We can use this like:

memofied = memoize(really_long_calculation);
result = memofied(1);  // calls really_long_calculation
result = memofied(1);  // uses cached value
memofied.clear();      // clear cache        
result = memofied(1);  // calls really_long_calculation again

      

The function is sufficient for an object that can be called Object.defineProperty

, which allows us to write the memoization function above as follows, if we really wanted to:



function memoize(fn) {
    var cache = {};
    return Object.defineProperty(function (x) {
        return x in cache ? cache[x] : cache[x] = fn(x);
    }, 'clear', {value: function() { cache = {}; } });
 }

      

(since it Object.defineProperty

returns an object.) This has the advantage of clear

using the default non-enumerable and non-enumerable properties, which seems useful.

I could even use a function as the first (prototype) argument for Object.create

:

someobj = Object.create(function() { }, { prop: { value: 1 } });

      

but there is no way to call the prototype function. However, its properties will be available on the prototype chain of the created object.

+1


source







All Articles