什么是this?
- 解析器在调用函数每次都会向函数内部传递一个隐含的参数,这个隐含的参数就是this,并且this指向一个对象,这个对象我们称之为函数执行的上下文对象。
this指向总结
- 当this不在函数内时,this指向永远为Window
- 以函数的形式调用时(function定义),this永远都指向Window
- 以方法的形式调用时(function定义),this指向调用该方法的那个对象
- 箭头函数不绑定this,this指向为定义时所在对象(或者可以理解为继承了外部的this)
- 构造函数中的this与被创建的新对象绑定
- call、apply、bind可以改变this的指向,使其指向传入对象
this指向分析
1. 当this不在函数内时
- 当this不在函数内时,this永远指向Window
var name = "张三"
var a = {
name: "李四",
children: {
name: this.name, // 张三
obj: this // Window
}
}
console.log(a.children.name)
console.log(a.children.obj)
2. 以函数的形式调用时(function定义)
- 以函数的形式调用,其实是call语法糖,传入参数是Window 即:
var name = "张三";
function sayHello(person) {
console.log(`你好${this.name},我是${person}!`);
}
sayHello("李四"); // 你好张三,我是李四!
// 即为 sayHello.call(Window, "李四") 的语法糖
// sayHello("李四") === sayHello.call(Window, "李四")
- 易混淆的地方:
var name = "张三"
var a = {
name: "李四",
hello: function () {
console.log(this) // Window
console.log(this.name) // "张三"
}
}
var b = {
name: "王五",
hello: function(fun) {
fun()
}
}
b.hello(a.hello)
注意:
即使函数调用的位置是在另一个函数内,或以参数形式传入,this指向也是Window!!
3. 以方法的形式调用时(function定义)
- 以方法形式调用时,也是call语法糖,但是传入参数是方法所在的对象
var name = "张三"
var a = {
name: "李四",
hello: function () {
console.log(this.name)
}
}
a.hello() // 李四
// a.hello() === a.hello.call(a)
4. 箭头函数中的this指向
- 箭头函数中的this是在定义函数的时候绑定的,而不是在执行函数的时候绑定的
- 箭头函数根本没有自己的this,导致箭头函数内部的this就是定义时所在的对象(或者可以理解为继承外层的this)
- 正因为箭头函数没有this,所以不能用作构造函数
var name = "张三"
var a = {
name: "李四",
children: {
name: "王五",
obj: this, // Window
hello1: () => console.log(this, this.name) // Window 张三
}
}
a.children.hello1()
// 定义a对象时,a所在对象为Window
// 所以a内的箭头函数的this为Window
a.children.hello2 = () => cosole.log(this, this.name) // Window 张三
// 定义a.chidren.hello2时,a.chidren.hello2整体所在对象也为Window
// 或者也可以理解为 继承了 children对象 中的this,即Window
a.children.hello2()
- 易混淆的地方:
var name = "张三";
var a = {
name: "李四",
hello: function() {
return () => console.log(this, this.name)
// { name: "李四", hello:f } 李四
}
}
a.hello()();
注意:
a.hello为function定义,遵循第三条规则,所以a.hello中的this指向a,所以a.hello() 箭头函数中的this指向a
与function定义的函数的区别:
var name = "张三"
var a = {
name: "李四",
children: {
name: "王五",
hello: function () {
return console.log(this, this.name)
}
}
}
a.children.hello() // { name: "王五", hello: f } 王五
// 这里遵循第三条规则,this指向children对象
5. 构造函数中的this指向
- 构造函数中的this与被创建的新对象绑定
function Hello(name) {
this.name = name
console.log(this) // Hello { name: "张三" }
console.log(this.name) // 张三
}
var a = new Hello("张三")
// 现在 Hello构造函数中的this指向即为 a
6. call、apply、bind对this指向的影响
- call、apply、bind都可以改变this的指向,使其指向传入对象
b.call(a) // this由b指向a
b.apply(a) // this由b指向a
b.bind(a) // this由b指向a
// 三者具体用法及区别请查阅官方文档