Search code examples
javascriptjavascript-objectsprototypejs

Why the nested function doesn't becomes the property of the outer function in javascript?


I have a code as follows:

function t() {
    var name = "abc";
    bar = function() {
    console.dir(this);
    console.log('bar');
 };
};
t.foo = function() {
    console.dir(this);
    this();
    console.log('bar');
};
console.dir(t);

It gives ouput as follows:

ƒ t()
foo: ƒ ()
arguments: null
caller: null
length: 0
name: "t"
prototype: {constructor: ƒ}
__proto__: ƒ ()
[[FunctionLocation]]: VM2091:1
[[Scopes]]: Scopes[2]

So we can see that, on inspecting function t(), we don't find function "bar", but function "foo" is in the function t().My question is that why function "bar" is not a property of function t(), while function "foo" becomes a property of function t()?


Solution

  • You can add properties to any JS object, including functions. So it's no surprise that t.foo = ... works and is displayed as a property when you log t to the console. The fact that the value t.foo points to is a function is purely incidental--it could just as well be a string, number or anything else.

    A function-scoped variable like bar is the same as any other defined in a function body; it's not a property of the function and doesn't exist until the function is executed. bar declares a global variable, so it's bound to window.bar and persists after the function executes. If it were local, it'd be destroyed when the function returns.

    You could use foo.bar to set a property on the function object from inside foo, but I can't imagine this would be useful for much.

    function foo() {
      foo.baz = 42;
    }
    
    foo.bar = 43;
    foo();
    console.log(foo.bar, foo.baz);

    In your functions, this will be window if these functions aren't bound to any object. If you want to bind this to a new object and set properties on it using the function constructor, create an instance using the new operator:

    function Foo() {
      this.bar = 42;
      this.quux = function () {};
    }
    
    Foo.prototype.baz = 43;
    Foo.prototype.corge = function () {};
    
    console.log(new Foo());

    The distinction here is that the this. functions are created whenever the constructor function is called and Foo.prototype. variables are only defined once.