前端面试,总是会被问到这样一类问题:
- 来来来,给你看下面这一段程序,这里的this.bar打印出来是什么值?下面这个this.bar打印出来又是什么值呢?

之前,我们已经在《前端面试题——十分钟搞懂this》介绍了this的各种规则,我这段时间看到了几个关于this的题目,那么这篇文章就让我们实战演练一下this的指向问题!
This指向规则
This指向分为四种绑定规则:默认绑定、隐式绑定、显式绑定以及关键字new绑定。在ES6之后,又有了箭头函数中的this规则。我们用实例看看,this在这些情况下的值是怎样的:
实例一
function foo() {
console.log(this.bar);
}
var bar = "bar1";
var o2 = {bar: "bar2", foo: foo};
var o3 = {bar: "bar3", foo: foo};
foo();
o2.foo();
foo.call(o3);
很容易,三个函数调用分别输出:”bar1”, ”bar2”, ”bar3”。因此这三者分别是默认绑定、隐式绑定和显式绑定。
实例二
再看下面这个例子:
var name = 'Nicolas';
function Person(){
this.name = 'Smiley';
this.sayName=function(){
console.log(this);
console.log(this.name);
};
setTimeout(this.sayName, 0); // 第二次输出
}
var person = new Person();
person.sayName(); // 第一次输出
这里的输出就需要仔细思考一下了。第一次输出的是Person, Smiley。第二次输出的结果是window,Nicolas。尽管setTimeout是在构造函数中定义的,但是调用的时候,是在window中调用。SetTimeout等许多之后被触发的事件当中,一定要注意this的指向,这是基于调用点(call stack)的 。
实例三
我们看下面这个例子:
function Person() {
this.name = "Smiley";
this.sayName = function(){
console.log(this);
console.log(this.name);
};
}
let person = new Person();
person.sayName.call({name: "Nicolas"});
这里的输出是{name: "Nicolas"}和”Nicolas”,是显式绑定。
如果接下来,我们让
function Person() {
this.name = "Smiley";
this.sayName = function(){
console.log(this);
console.log(this.name);
};
}
let person = new Person();
let sayNameCopy = person.sayName;
sayNameCopy();
这次会得到什么呢?答案是window和undefined。因为,这个时候符合默认绑定的规则。
那么这个例子呢?
function Person() {
this.name = "Smiley";
this.sayName = ()=> {
console.log(this);
console.log(this.name);
};
}
let person = new Person();
person.sayName.call({name: "Nicolas"});
我们只改动了一处:把sayName改为箭头函数。结果则变成了Person和"Smiley"。这是因为箭头函数并没有自己的this,被定义在哪里,this就指向谁,且优先级比显式调用高,因此,this仍指向Person。
好啦,这就是我最近看到的关于this的几道问题 。希望看完这篇文章之后,再也不会为this感到头疼,如果你看到关于this的有趣的问题,也欢迎分享给我。祝大家前端学习一切顺利。
关注我的公众号:前端三剑客,分享前端和算法面试题目

本文通过实例解析JavaScript中的this绑定规则,包括默认绑定、隐式绑定、显式绑定、new绑定以及箭头函数中的this。分析了setTimeout等异步调用中this的变化,并探讨了构造函数和箭头函数对this的影响,帮助读者掌握this的实战运用。
16万+

被折叠的 条评论
为什么被折叠?



