0
var obj={
            say: function(){
                console.log(obj); // undefined
            }()
        };

It finally output undefined.And I began to explain it using the knowledge of execution context,but I felt doubt about when the method is created in the context.

I know that after entering the context,we first enter the creation phase and have a variable object which includes the variable and function declarations.Next we enter the execute phase and finish the assignment of varibale and function.So in this example,we:

First,enter the creation phase of the global excution context,and the obj is undefined. Next,after the creation phase,we enter the execute phase.The codes begin to excute and obj now points to an object.However,in the process above,when the say method is created?During the creation phase of global execution or the execute phase of the global execution?

(If during the creation phase,then the variable object of the global execution context should be AO={ obj:undefined,say: referencce to <function>})

Or is there any better way to explain why here the result is undefined? I have searched online and saw someone say this is because hoisting.Is it correct?

Chor
  • 833
  • 1
  • 5
  • 14
  • That is not a method, it is a property containing `undefined` (because the IIFE doesn't return anything). Remove the parenthesis from the end of the function, that way you'll have a method. And this has nothing to do with hoisting. – Teemu Apr 12 '19 at 11:29
  • @Chor I think you posted a comment on my answer but then deleted it before I could read it. I would be happy to further this discussion, feel free to share any thoughts or concerns you may have :) – etarhan Apr 12 '19 at 13:36
  • Sure, I have to finish the comment completely (Just click enter and send the unfinished message) – Chor Apr 12 '19 at 13:38

1 Answers1

1

It is because you are immediately calling the function without assigning the value of obj. Compare the two scenarios in the bottom snippet:

var obj = {
  say: function() {
    console.log(obj); // Not undefined since it will run after obj is assigned
  }
};
obj.say();

var objUndef = {
  say: function() {
    console.log(objUndef); // undefined
  }() // <--- immediately calling
};
In your example you are not assigning a function, but rather the result of a function (because you call it immediately with ()), which is running before obj is even assigned. Thus the result is that you log undefined to the console instead of the obj value. If you first create the object and later call its say method using obj.say(), obj will be defined since you assign obj first before you attempt to call it.
etarhan
  • 4,138
  • 2
  • 15
  • 29
  • ok,I get it.But another question is : for the first scenario(which is without parenthesis ),when will the `say` method be created during the creation phase (before the codes actually be executed ) of the global execution context? Does the AO of the global execution context look like `AO={ obj:undefined,say: referencce to }`?Or look like `AO={ obj:undefined}`? – Chor Apr 12 '19 at 13:45
  • `var a = 1; function foo(){ ..... } foo();` Take the above codes for example.First enter creation phase of the global execution context and the AO(window object) should be `AO ={a:undefined,foo:reference to } `.Then enter the execution phase of the global execution context,now the AO should be` AO={a:1,foo:reference to }`.At this moment,the foo function also be created(as well as the `[[Scope]]` property). – Chor Apr 12 '19 at 13:59
  • The codes continue executing until encounter `foo()`.Once encountering it,the execution context will turn into function execution context.But in our case,the function is not in the global context but in the object(`obj`).In this case,when will the function be created? @etarhan – Chor Apr 12 '19 at 14:00
  • The execution context of the function is different from the global context. The global context has a reference to the obj, which contains property with a function which you immediately call. This causes a new execution context to be created and pushed to the top of the stack for the inner function call, before finishing the creation phase of in the global context, resulting in obj being undefined. – etarhan Apr 12 '19 at 14:01
  • @Chor the moment you invoke a function you will immediately enter a new execution context which will be pushed to the top of the stack. This execution will be completed before being popped off the stack and after which you return to you initial context – etarhan Apr 12 '19 at 14:04
  • @etarhanYes I know the function context will be on the top while the global context is always on the bottom.But I just want to know when is the function created.Does it exist exactly during the creation phase of the global excution context? – Chor Apr 12 '19 at 14:12
  • @Chor yes the function exists in the creation phase, that's not the issue. During the code execution phase it will first invoke the function (since your example had a IIFE) before it can assign the value to `say`, meaning BEFORE the obj is assigned as well, causing the reference to obj inside the function to be undefined – etarhan Apr 12 '19 at 14:25