1.关于 this 指向的几种情况
- 以函数形式调用时, this 永远都是 window
- 以方法的形式调用时,this 是调用方法的对象
- 以构造函数的的形式调用时,this 是新创建的那个对象
- 定时器和计时器的 this 默认指向 window
- 箭头函数的 this 看外层是否有函数:如果有,外层函数的 this 就是内部箭头函数的this,如果没有,就是 window
- 严格模式下(设置了'use strict'),this为undefined
- 特殊情况:通常意义上 this 指向最后调用它的对象,这里需要注意的一点是,如果返回值是一个对象,那么 this 指向的就是那个返回值的对象,如果返回值不是一个对象,那么 this 还是指向函数的实例
<script>
function fn() {
console.log(this, '1')//window
}
fn()//调用才会打印
let obj = {
name: '前端小白兔',
age: 18,
eat: function () {
console.log(this, '2')//Object
setTimeout(function () {
console.log(this, '3')//window
}),
setTimeout(()=>{
console.log(this,'4')//Object
})
},
}
obj.eat()//调用才会打印
function Person(name, age) {
this.name = name,
this.age = age,
this.sayHi = function () {
console.log(this, '5')//new Person
return `我是${this.name},今年${age}岁!`
}
}
let p = new Person('Lucy', 18)
p.sayHi()//调用才会打印
setTimeout(function () {
console.log(this, '6')//window
}, 1000)
setInterval(function () {
console.log(this, '7')//window
}, 5000)
function getSum() {
'use strict'
console.log(this, '8')//undefined
}
getSum()//调用才会打印
</script>
2.修改 this 指向的方式
使用函数上下文调用模式 : 修改this指向
- 函数名.call(修改后的this,实参1,实参2......),适用于少量形参
- 函数名.apply(修改后的this,数组/伪数组),适用于多个形参
- 函数名.bind(修改后的this,实参1,实参2......),适用于不需要立即执行的函数(定时器函数,事件处理函数),得到一个修改this之后的新函数
<script>
//◆函数名.call(修改后的this,实参1,实参2......)
function fn1(a, b) {
console.log(this, '1')
return a + b
}
fn1.call({ name: '张三' }, 20, 80)
//◆函数名.apply(修改后的this,数组/伪数组)
function fn2(a, b, c) {
console.log(this, '2')
}
fn2.apply({ name: '李四' }, [20, 80, 90])
//◆函数名.bind(修改后的this,实参1,实参2......)
function fn(a, b) {
console.log(this, '3')
return a * b
}
let newFn = fn.bind([50, 100], 50, 100)
console.log(newFn(70,80),'6')//5000
// 具名函数
function test() {
console.log(this, '4')
}
setTimeout(test.bind({ name: '前端小白兔' }), 2000)
// 匿名函数
setTimeout(function () {
console.log(this, '5')
}.bind({ name: '斩妖除魔' }), 2000)
</script>
小细节:如果调用bind传递了参数,则参数也会绑定,之后调用的时候无法传参; 如果bind绑定的时候不传参数,则不绑定参数,后面就可以传其他的参数
3.函数上下文三种调用方式的区别
- 传参方式不同:call 用于单个传参,apply 用于多个传参
- 执行机制不同:call 和 apply 会立即执行,bind 不会立即执行
4.函数上下文调用模式中:this 指向只能是引用类型
如果你传的不是引用类型,编译器会自动帮你转成对应的引用类型
<script>
function fn() {
console.log(this)
}
fn.call(1)//内置对象Number
fn.call('你好呀上帝')//内置对象String
fn.call(Symbol('A'))//内置对象Symbol
fn.call(undefined)//window
fn.call(null)//window
fn.call()//window
</script>
如果 this 修改为 undefined 或 null ,此时 this 修改无效的,还是之前的this