在前端开发中this的指向问题是一个非常基础也很重要的知识点,是开发人员绕不过去的一个问题。那么今天用几个面试题来聊一聊前端中this问题吧.
首先需要知道一点:this 永远指向最后调用它的那个对象,通俗一点就是指向他爹。
this 指向
案例 1
this.value = "value";
function fn() {
var value = "innerValue";
console.log(this.value);
}
fn(); // value
这个题大家应该都知道答案肯定是打印value,那么为什么打印的结果是value呢?看刚才那句话this 永远指向最后调用它的那个对象,这个时候我们就想了究竟是谁调用了fn呢?其实就是window,这个时候我们就清楚了,哦原来是widnow调用了fn,所以这个this就指向了window,因此就输出打印value。
案例 2
this.num = 30;
const obj = {
num: 20,
fn: function () {
console.log(this.num);
},
};
obj.fn(); // 20
var fn = obj.fn;
fn(); // 30
分析:
- 默读三遍this 永远指向最后调用它的那个对象,this 永远指向最后调用它的那个对象,this 永远指向最后调用它的那个对象
- 根据
案例1的思路,是obj调用的fn,函数内部this指向的是obj,所有打印输出obj.num的值20 - 接下来我们声明了一个全局变量
fn=obj.fn,调用fn()等同于调用window.fn(),所有打印输出window.num的值30
案例 3
难度加大一点
this.a = 20;
function go() {
console.log(this.a);
this.a = 30;
}
go.prototype.a = 40;
var test = {
a: 50,
init: function (fn) {
fn();
console.log(this.a);
return fn;
},
};
//输出1
console.log(new go().a);
// 输出2
test.init(go);
var p = test.init(go);
p();
在做这个题目之前,首先有一个知识点需要清楚,代码如下,首先会找对象的值,然后再去找原型对象的值。也就是说p.a的时候会先在对象上获取这个值,没有则在原型对象上获取,明白了这个就好了。
function P() {
this.a = 1
}
P.prototype = 2
let p = new P()
console.log(p.a) // 1
分析:
-
首先实例化一个对象
new go(),同时调用函数go,代码执行console.log(this.a),此时的this是指向实例化对象,按照 刚才的所说的,先找对象上的key值,发现没有,然后找原型对象上的a,发现go.prototype.a = 40所以打印40,同时this.a = 30,然后获取new go().a重复上一步的思路,先读取对象的key值发现存在且为30,所以整个的结果就是先输出40,然后输出30 -
调用
test.init(go),首先调用go方法,我们可以这里理解test.init(window.go),其实就是调用window.go(),首先打印this.a,也就是window.a,发现全局声明了this.a=20,所以打印20,同时注意接下来的this.a=30,已经将全局的a改变了此时的window.a=30,接下来执行console.log(this.a);,此时的this指向test,所以输出打印50,因此最后的结果就是先输出20,然后50 -
执行
var p = test.init(go),重复步骤2首先调用全局函数go,打印全局的a,步骤2中更改了全局a的值为30,所以先输出30,然后调用test对象的init方法,执行console.log(this.a),因此打印50,最后定义了一个全局p,并返回了一个函数go,执行p(),也就是执行window.p(),此时的window.a===30所以打印30,最终的输出就是30,50,30 -
综合以上分析最终的输出就是40,30,20,50,30,50,30