就一句话:函数也是对象。
为什么这个认知能帮我们理解this指向问题?且由我来为客官们解读。
第一部分:函数作为对象的本质
函数是特殊的对象
既然函数是对象 ,那么函数也就有属性和方法

代码示例:
javascript
// 函数是对象,有属性和方法
function myFunction() {
console.log("Hello");
}
// 函数对象的属性
console.log(myFunction.name); // "myFunction"
console.log(myFunction.length); // 0 (参数个数)
console.log(myFunction.prototype); // 原型对象
console.log(typeof myFunction); // "function"
那么就知道函数的属性可以存储数据与函数的方法可以控制函数的行为。
函数对象的特殊方法
函数对象的原型链上有call、apply、bind等方法,这些方法能控制函数执行时的this 指向,说明了this的指向是可以被控制的。

代码示例:
javascript
function test() {
console.log(this.name);
}
// 函数对象有三个重要方法
test.call(obj); // 立即执行,this 指向 obj
test.apply(obj); // 立即执行,this 指向 obj
test.bind(obj); // 返回新函数,this 永久绑定到 obj
第二部分:this指向的确定
this指向有四种情况,分别为普通函数调用 、方法调用 、构造函数调用 和间接调用。
情况1: 普通函数调用
javascript
function func1() {
console.log(this); //this 指向window (非严格模式)
}
func1(); // 独立调用
情况2: 方法调用
javascript
var obj = {
method: function() {
console.log(this); // this 指向obj
}
};
obj.method(); // 通过对象调用
情况3: 构造函数调用
javascript
function Person(name) {
this.name = name; // this 指向新创建的对象
}
var person = new Person("John");
情况4: 间接调用
javascript
function func2() {
console.log(this);
}
func2.call(obj); // this 指向 obj
this的指向取决于函数的调用方式,不同方式会产生不同的this指向,说明了this是动态的,不是静态的。
少侠请听题:
判断一下会输出什么?
javascript
var name = "The Window"
var object = {
name: "My object",
getNameFunc: function() {
return function() {
return this.name;
};
}
};
console.log(object.getNameFunc()());
答案是The Window。
Why?因为是独立调用 ,返回的是一个立即执行函数,过程可以拆解为 var returnedFunc = object.getNameFunc()先获取到了函数,再执行returnedFunc()独立调用 ,this 指向了window。问题的根源其实就是返回的函数失去了原来的对象上下文。
那我们要输出My object怎么办?
方法一: 使用闭包来捕获变量
javascript
var name = "The Window"
var object = {
name: "My object",
getNameFunc: function() {
var that = this; // 添加这里
return function() {
return that.name;
};
}
};
分析: object.getNameFunc()执行时,this指向了object,因为将this赋给了that,将object的引用保存到了that,返回内部函数,该函数形成了闭包,能够访问that,内部函数被独立调用 的时候,this指向了window,但that仍然指向object,于是就能够输出My object。
方法二: 使用箭头函数
javascript
var name = "The Window"
var object = {
name: "My object",
getNameFunc: function() {
return () => {
return this.name;
};
}
};
分析: object.getNameFunc() 执行时,this 指向 object,由于箭头函数没有自己的this,定义时this就确定了,不会在调用时改变(词法作用域 ),this会继承所在作用域(即 getNameFunc)的 this,指向 object。于是也能够输出My object。
方法三: 使用bind方法
javascript
var name = "The Window"
var object = {
name: "My object",
getNameFunc: function() {
return function() {
return this.name;
}.bind(this); // 显式绑定 this
}
};
总结
函数作为对象的特性(有方法、有属性、可以形成闭包)提供了多种解决 this 指向问题的工具和方法。