某日,跟公司大牛交流学习进步的方法,大牛说:要善于总结,技术总结很重要。于是自己想动手写点东西,总结一下自己近期学到的一些技术点,踩到的坑,也算是对自己一个技术复盘与总结。(作者表达能力一般,可能有表达错误或不准确的地方,欢迎纠正与交流。第一次写,有点小激动0.0)。
在工作中或面试过程中,经常会碰到有关this指向的问题,似曾相识的场景,却总是被混淆分不清,中了面试官的套路。这段时间作者研究了下,简单总结一波
1,默认规则。举个栗子,代码如下:
var name = '小明';function print() { console.log(this.name); // '小明' console.log(this); //window对象}print(); 复制代码
这里我们看到打印出来的是小明,this.name被解析成了全局对象,this指向的是window对象。why?为什么this会指向window呢,因为在本例中,函数调用时应用了this的默认绑定原则,因此this指向的是全局对象。那我们怎么判断当前应用了默认绑定呢,我们可以通过函数的调用位置来判断,我们发现print函数是直接调用的,不经过任何修饰。因此只能使用默认绑定,无法使用其他原则
2,隐式绑定
function foo() { console.log(this.a)}var obj = { a:2, foo:foo}obj.foo() // 2复制代码
这里我们看到foo函数的调用者是obj对象,此时this绑定到了obj上,所以this.a输出的是obj.a。这种情况称之为隐式绑定:当函数引用有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象。好,这个时候我们应该对隐式绑定有个大概的了解,那当函数有多个引用的时候会怎么样呢?让我们来看一道题:
var obj = { a:1, foo:function() { console.log(this.a) }}var obj1 = { a:2, obj:obj}obj1.obj.foo() // 1复制代码
我们看到这种情况下this指向的是最后一层的对象上,即obj上。隐式绑定一定都是这样的吗,答案式否定的,这里面有一个坑:有些时候会发生隐式绑定丢失的情况。让我们来举例说明:
var a = 'hello world';function foo(){ console.log(this.a)}var obj = { a:1, foo:foo}var print = obj.foo;print(); // hello world复制代码
这里我们发现隐式绑定规则失效了,this.a输出的不是1,而是全局对象上的a。这又是怎么回事呢?其实print,obj.foo都是函数的引用。直接调用print函数式,相当于直接调用foo函数,是不是很熟悉呢?没错,是默认绑定,所以此时this指向的是window。所以说我们在判断是否是隐式绑定的时候需要仔细些,分清楚情况。
3,显示绑定
何为显示绑定?利用call(),apply(),bind()强制绑定this指向的我们称之为显示绑定。举个栗子:
function foo() { console.log(this.a);}var obj = { a:1}foo.call(obj); // 1复制代码
这里我们看到通过call方法将this强制绑定到了对象obj上。利用bind()函数绑定this的做法我们又称之为硬绑定,硬绑定之后当前函数的this指向无法再修改,举个栗子:
var a = 'hello world';function foo() { console.log(this.a);}var obj = { a:1}var print = foo.bind(obj);print(); // 1// 利用call方法强制将this绑定在window上,但是失败了,this还是指向objprint.call(window); // 1复制代码
call(),apply(),bind()这三个函数有什么区别,这里就不一一阐述了,有兴趣的同学可以去了解下。
4,new绑定
这个相信大家平时编程时会遇到过很多次,这里简单说明下,如下:
function Person(name) { this.name = name;}var p = new Person('小明');console.log(p.name); // 小明复制代码
这种情况我们称之为new绑定。
this绑定的四种基本规则我们基本弄清楚了,那么它们的优先级是什么样的呢?这里我们直接给出结论,不在一一举例对比说明了,有兴趣的同学可以自己举例对比下。优先级:new绑定 > 显示绑定 > 隐式绑定 > 默认绑定。我们在判断this指向的时候可以按照这个优先级顺序来判断,绝大部分情况都可以适用。
参考文献:《你不知道的JavaScript》,很nice的一本书!复制代码