Beginners about this understanding has been very vague, about this interview questions more make head big.
This is the body of the function execution (by whom) remember: who is this and where the function was created or executed
Most interview questions can be easily solved by following these rules to distinguish the subject of execution.
1. Bind a method to an event on an element that triggers the execution of the methodthis
Is the element of the current operation (implicit binding)
document.body.onclick = function() {
// this: body
}
Copy the code
Typically, the value of this is a reference to the element that triggered the event, which is desirable when multiple similar elements use the same common event listener. When an element is registered for an event using addEventListener(), the this value in the handle is a reference to the element. This is the same as the value of the currentTarget property of the Event argument passed to the handle.
2. Execute the method to see if there is any (.) in front of the method. If there is, who is in front of the dotthis
That’s who (implicit binding), no pointthis
iswindow
(In strict mode (“use strict
“) no pointthis
isundefined
, also known as default binding)
Note: the self-executing function(‘ (function(){… })() ‘this’ is usually a window
function fn() {
console.log(this)}let obj = {
fn: fn
}
fn()
obj.fn()
Copy the code
Output: Window object obj object
The above code is equivalent to:
let obj = {
fn: function fn() {
console.log(this)
}
}
fn()
obj.fn()
Copy the code
Functions are defined inside objects, but they are qualitatively equivalent to declaring functions outside objects and then referencing functions inside objects by property names.
In a chain of object properties,this
The binding is the innermost object
As follows:
var obj = {
a: 1.obj2: {
a: 2.obj3: {
a: 3.getA: function () {
console.log(this.a)
}
}
}
}
obj.obj2.obj3.getA()
Copy the code
This: obj.obj2.obj3
3. In constructor mode execution, in the function bodythis
Is an instance of the current class
When the new operation is performed, a new object is created and the constructor’s this points to the new object being created. The JS compiler does four things:
- Create a new empty object
- Link this object to the prototype object
- This object is bound to this
- If the function returns nothing, then return this by default
function Fn(name) {
// this: instance of the Fn class
this.name = name
}
var f1 = new Fn('qxj')
var f2 = new Fn('lx')
console.log(f1.name)
console.log(f2.name)
Copy the code
Output: QXJ Lx
4. Call /bind/apply can be changedthis
Pointing to (explicit binding)
Call (object) FN: the function you call, object: the object you want to bind to this of the function. Fn. Call (object)
- Call this function now (fn)
- When this function is called
this
Point to object
Example:
var obj = {
a: 1.// A is an attribute defined in object obj
fire: function () {
console.log(this.a)
}
}
var a = 2 // A is a variable defined in the global environment
var fireInGrobal = obj.fire
fireInGrobal() / / = > 2
fireInGrobal.call(obj) / / = > 1
Copy the code
FireInGroba, which lost the this parameter bound to obj, rebinds this back to obj
However, we don’t like the idea of relying on call every time. We would prefer to return this once and permanently bound to obj’s fireInGrobal function so that we don’t have to put call on the tail every time we call fireInGrobal.
What to do? This is even easier if you use bind
var fireInGrobal = function () {
fn.call(obj) / / hard binding
}
Copy the code
It can be simplified as:
var fireInGrobal = fn.bind(obj);
Copy the code
Call differs from bind: while binding this to an object parameter:
-
Call will execute this function immediately
-
Bind does not execute functions, only returns a function that can be executed
【 Others 】 : Apply is not much different from Call except how it is used
5. Arrow function
The arrow function ignores all of these rules, and the value of this is the lexical scope of the function’s creation, independent of how it was called. Compare these two examples:
function Person() {
this.age = 0
setTimeout(function () {
console.log(this.age) // => undefined
}, 1000)}var p = new Person()
function Person() {
this.age = 10
setTimeout((a)= > {
console.log(this.age) / / = > 10
}, 1000)}var p = new Person()
Copy the code
In the example above without the arrow function, the function inside setTimeout is called by global, which has no age property, so undefined is output.
The second example uses the arrow function, and this uses this of the lexical scope, which is Person, so it prints 10.
According to the MDN document, the value of this of the arrow function is the environment when it is created. Although the point of this in the arrow function cannot be changed by bind, call, apply and other operations, the value of this in the external environment can be changed. In other words, to change this of the arrow function, you only need to change this of the external environment. Consider the following examples:
const obj = {
name: 'this point to obj,
bar() {
const x = (a)= > this
return x
},
}
console.log(obj.bar()())
const a = {name: 'this points to a'}
const b = {name: 'This refers to b instead of obj and a'}
console.log(obj.bar.bind(b)().call(a))
Copy the code
Output:
Summary: Binding priority
- Arrow function
- Keyword new tone
- Explicitly bound
- Implicit binding
- The default binding
The arrow function has the highest priority and ignores binding rules 2-5. The default binding has the lowest priority. The default binding is used only when no other binding is used.
6. A few interview questions
eg1:
var fullName = 'language'
var obj = {
fullName: 'javascript'.prop: {
getFullName: function () {
return this.fullName
}
}
}
console.log(obj.prop.getFullName())
var test = obj.prop.getFullName
console.log(test())
Copy the code
Output: javascript language
This is obj.prop. GetFullName (). This is obj.prop. FullName is javascript. Test () is not preceded by a dot, this is window, and window.fullname is language;
eg2:
var val = 1
var json = {
val: 10.dbl: function () {
val *= 2
}
}
json.dbl()
console.log(json.val + val)
Copy the code
Output: 12
Json.dbl () : this = json; val== 10; val==2; val==2; Json. val + val => 12;
Let’s change the title:
var val = 1
var json = {
val: 10.dbl: function () {
this.val *= 2
}
}
json.dbl()
console.log(json.val + val)
Copy the code
Output: 21
var val = 1
var json = {
val: 10.dbl: function () {
this.val *= 2 // json.val = 20
}
}
json.dbl() // The method starts with this: json
console.log(json.val + val) // 20 + 1 => 21
Copy the code
eg3:
var num = 10
var obj = {num: 20}
obj.fn = (function (num) {
this.num = num * 3
num++
return function (n) {
this.num += n
num++
console.log(num)
}
})(obj.num)
var fn = obj.fn
fn(5)
obj.fn(10)
console.log(num, obj.num)
Copy the code
Output: 22, 23, 65, 30