var bar = {
myName: 'bar',
printName: function () {
console.log(this.myName)
}
}
function foo() {
let myName = 'foo'
return bar.printName
}
let myName = 'outer'
let _printName = foo()
_printName()
bar.printName()
Why the result of the first function execution is undefined ? I thought the result would be 'outer', and why output 'outer' after changing let to var ? This is so confusing, please help me.
Why the result of the first function execution is undefined ?
Because you don't bind this
to anything in the function call (you neither have objectThatWillBecomeThis.printName()
nor printName.call(objectThatWillBecomeThis)
). In strict mode, this would crash because this
would be undefined
then and you'd try to read undefined.myName
. But since you didn't enable strict mode, the legacy behavior is active in which this
- when not explicitly set - will be set to the global object. However, the global object doesn't have any property myName
(in the browser: there is no window.myName
) so the result is undefined
.
why output 'outer' after changing let to var ?
Because if you run this code in the global scope, var
outside of any other scope will create a property on the global object (window.myName
). let
doesn't do that:
At the top level of programs and functions,
let
, unlikevar
, does not create a property on the global object. For example:var x = 'global'; let y = 'global'; console.log(this.x); // "global" console.log(this.y); // undefined
If you'd move the code inside a function, it wouldn't work either, by the way, because the var
(or let
, doesn't matter now) statement would just create a local variable in the function and not a property on the global object, so there would be no way to access it through any object's myName
property.