Disclaimer
This article is originally based on my understanding of this concept. No guarantee on the accuracy.😅
The weird This
This
was property of a certain context, that is to say, in global context or a function contexThe ECMA 2015
Note:
A Reference
is a resolved name binding. A Reference consists of three components, the base value
, the referenced name and the Boolean valued strict reference flag. The base value is either undefined, an Object, a Boolean, a String, a Number, or an environment record
1 | var foo = (){console.log(this.value)}; |
- In
strict mode
,This
in global context refers to undefined, innon-strict mdoe
it refers to the window object - Inside a function ,
This
pointer was determined when the function was invoked:- During the creation phase the
this
was initialized asundefined
- Then during the execution phase the
this
- Therefore, whom the
This
pointer points to, is subjected to how the funciton was called, which means what is on the left of the()
operator
- During the creation phase the
- A function can be invoked in the following ways by different
CallExpression
- Function invocation => CallExpression Arguments
- Method invocation => CallExpression [ Expression ] CallExpression . IdentifierName
- Constructor invocation => new MemberExpression Arguments
- Indirect invocation =>MemberExpression Arguments
Function inovation & method invoation
- When a function is called as a method of an object, the object is passed to the function as its this value.
1 | let value = 'window'; |
foo()
​ foo->MemberExpression=>ref: foo => declaritive enviorment record => global object
obj.foo()
​ obj.foo => ref=> base=>obj
obj.inner.foo()
​ obj.inner.foo => base => inner
(obj.foo=obj.foo)()
​ ‘=’ assignmetn oprator ->call GetValue -> return a value not a reference => global
doFoo(fn)=>fn()
​ arguments: fn = obj.foo => call GetValue -> return a value not a reference => global
Constructor invocation
According to ECMA2015, the new operator would call the [[construct]] inner method of a function
​ Let obj be a newly created native ECMAScript object.
​ Let result be the result of calling the [[Call]] internal property of F, providing obj as thethis
value and providing the argument list passed into [[Construct]] as args.
​ If Type(result) is Object then return result.
​ Return obj.
1 | var name = 'window' |
Arrow function
ArrowFunction : ArrowParameters
=>
ConciseBodyIf the function code for this ArrowFunction is strict mode code (10.2.1), let strict be true. Otherwise let strict be false.
Let scope be the LexicalEnvironment of the running execution context.
Let parameters be CoveredFormalsList of ArrowParameters.
Let closure be FunctionCreate(Arrow, parameters, ConciseBody, scope, strict).
Return closure.
lexical means that
this
refers to the this value of a lexically enclosing function.
before arrow function
This
is nothing to do with scope!!In arrow functions, JavaScript sets the this lexically. It means the arrow function does not create its own execution context, but inherits the this from the outer function where the arrow function is defined.
var name = 'window' var obj1 = { name: 'obj1', foo: function () { console.log(this.name) return function () { console.log(this.name) } } } var obj2 = { name: 'obj2', foo: function () { console.log(this.name) return () => { console.log(this.name) } } } var obj3 = { name: 'obj3', foo: () => { console.log(this.name) return function () { console.log(this.name) } } } var obj4 = { name: 'obj4', foo: () => { console.log(this.name) return () => { console.log(this.name) } } } obj1.foo()() // 'obj1' 'window' obj2.foo()() // 'obj2' 'obj2' obj3.foo()() // 'window' 'window' obj4.foo()() // 'window' 'window' <!--3-->
Combining constructor call and arrow function
1 | var name = 'window' |
1 | var name = 'window' |
Comparing with the constructor function:
1 | var name = 'window' |
For nested object inside a constructor function same rules applies
1 | var name = 'window' |
Strict mode
1 | function foo() { |
Comapring to:
1 | ; |
Ref: ECMA2015
Test source: Juejin