前言
this因指向灵活多变、使用场景多样,一直是面试中的热点。
谁调用它,this就指向谁
this的指向是在调用的时候确定的,也就是说找this的指向等于找谁调用它。
可这并不全面,它有以下几条规律:
- 在函数体系中,调用函数时,在严格模式下指向undefind,非严格模式指向window。(箭头函数除外)
- 在箭头函数中,this指向由外层作用域来决定。
- 一般用new方法构建函数时候,构建函数内的this会被绑定到新创建的对象上。
- 通过call/apply/bind 方法显示调用函数时,this会被绑定到指定的对象上。
- 一般通过上下文对象调用函数时,this会绑定到该对象上。
全局环境下的this
function fn1() {
console.log(this)
}
function fn2() {
'use strict'
console.log(this)
}
fn1(); // Window
fn2(); // undefined
这种状况相对简单。
上下文对象中的this
面对以下代码,我们将不会疑惑,最终true
const student = {
name: 'xxx',
fn: function() {
return this;
}
}
console.log(student.fn() === student) // true
当存在更多调用关系时,this会指向最后调用它的对象。
const dog = {
name: '二哈',
fn: function() {
return this.name;
},
child1: {
name: '小虎',
fn: function() {
return this.name
}
},
child2: {
name: '小黄',
fn: function() {
const fn = this.name
return fn
}
},
child3: {
name: '小3',
fn: function() {
const fn = dog.fn
return fn()
}
},
child4: {
name: '小4',
fn: function() {
const fn = dog.child1.fn()
return fn
}
}
}
console.log(dog.fn()); // 二哈
console.log(dog.child1.fn()); // 小虎
console.log(dog.child2.fn()); // 小黄
console.log(dog.child3.fn()); // undefined
console.log(dog.child4.fn()); // 小虎
在上面代码中,child3、child34提前做了赋值操作,将函数fn提前挂载到别的对象上。
通过bind、call、apply改变this指向
他们都是用来改变this指向的,但是call和apply是直接进行相关函数的调用,bind不会执行相关函数,而是返回一个新的函数,这个新的函数已经自动绑定this。说具体点call和apply之间区别在于形参上。
const object1 ={
name: 'xxx',
}
function fn() {
console.log(this.name)
}
function fn1(p1, p2) {
console.log(p1, p2)
}
fn.call(object1); // xxx
fn1.call(object1, 1, 2) // 12
fn.apply(object1); // xxx
fn1.apply(object1, [1,2]) // 12
fn.bind(object1)(); // xxx
fn1.bind(object1, 1, 2)() // 12
```构造函数和this
关于构造函数,我们先看下代码:
```js
function person() {
this.name = '小明'
}
const p1 = new person();
console.log(p1.name); // 小明
这可以简单看出构建函数this指向实列。但是如果在函数中使用了return,就要注意了:
function person() {
this.name = '小明';
return {}
}
function person1() {
this.name = '小红';
return 0
}
const p1 = new person();
const p2 = new person1();
console.log(p1.name); // undefined
console.log(p2.name); // 小红
结论:
构造函数中返回的是一个对象(复杂类型),那么this就指向这个对象;如果返回的是一个数字(基本类型),那么this仍然指向实列。
箭头函数中的this
先了解下箭头函数中的this:
箭头函数的this由其所属函数或全局作用域所决定。
如下巧用this:
const object1 = {
fn: function () {
setTimeout(function() {
console.log(this) // Window
}, 1000);
}
}
const object2 = {
fn: function () {
setTimeout(() => {
console.log(this) // {fn: ƒ}
}, 1000);
}
}
object1.fn();
object2.fn();
总结
谁跳用它,this就指向谁。