JavaScript里this的绑定优先级是怎么样的?

432 阅读3分钟

「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战

上篇我们已经了解了函数调用中 this 绑定的四条规则,但是,如果某个调用位置可以应用多条规则该怎么办?为了 解决这个问题就必须给这些规则设定优先级,这就是我们接下来要介绍的内容。

前言

👉 JavaScript里this的绑定规则

规则回顾

  • 默认绑定

    例:function foo(){...} foo() ,

    foo 中的 this 就是 window.(严格模式下默认绑定到undefined), 这样的绑定方式叫默认绑定 .

  • 隐式绑定

    函数是在某个上下文对象下被调用, this绑定的是那个上下文对象。

    例 : function foo(){...}; var obj = { foo : foo }; obj.foo();

    foo 中的 this 就是 obj 。这样的绑定方式叫隐性绑定

  • 显示绑定

    函数是使用call,apply,bind来调用的,this绑定的是 call,apply,bind 的第一个参数。、

    例: function foo(){...}; foo.call(obj);

    foo 中的 this 就是 obj , 这样的绑定方式叫显性绑定 .

  • new绑定

    函数被new 修饰,this绑定的是新创建的对象

    例:var bar = new foo();

    函数 foo 中的 this 就是一个叫foo的新创建的对象 , 然后将这个对象赋给bar , 这样的绑定方式叫 new绑定 。

优先级分析

毫无疑问,默认绑定的优先级是四条规则中最低的,所以我们可以先不考虑它。

隐式绑定和显式绑定哪个优先级更高?

function foo() { console.log( this.a ); }
var obj1 = { a: 2, foo: foo };
var obj2 = { a: 3, foo: foo };

//隐式绑定
obj1.foo(); // 2
obj2.foo();// 3 

//显示绑定
obj1.foo.call( obj2 ); // 3
obj2.foo.call( obj1 ); // 2

结论:显式绑定优先级大于隐式绑定

new 绑定和隐式绑定的优先级谁更高?

image-20211029231854420

结论:当同时存在于new关键字绑定和隐式绑定时,this绑定了foo构造函数,所以new关键字的优先级高于隐式绑定

new 绑定和显示绑定的优先级比较?

image-20211029232323177

结论:当同时存在于new关键字绑定和显示绑定时,this绑定了bar构造函数,所以new关键字的优先级高于显示绑定。

箭头函数的this

注意,箭头函数没有自己的this,它的this来源于上级作用域。

image-20211029233324417

如以上示例,同样是调用foo函数,因为箭头函数不绑定this,所以去foo函数的上级查找this,找到了全局对象window。

总结

四种绑定的优先级顺序为

new关键字 > 显式绑定 > 隐式绑定 > 默认绑定

判断this调用规则

  • 函数是否存在new绑定调用:如果是的话this绑定到新创建的对象上。var bar = new foo()
  • 函数是否通过apply、call、bind显示绑定:如果是的话,this绑定到指定对象上。var bar = foo.call(obj2)
  • 函数是否在对象方法隐式调用:如果是的话,this绑定到调用对象。var bar = obj1.foo()
  • 如果上面三条都不满足的话:在严格模型下,this绑定到undefined,在非严格模式下,this绑定到全局对象上。var bar = foo()

参考资料:

this & Object Prototypes


🎨【点赞】【关注】不迷路,更多前端干货等你解锁

往期推荐

👉 超详细的JS映射(Map)总结

👉 你真的了解JavaScript的解构赋值吗?

👉 JS内置日期对象Date的使用指南

👉 函数进阶之递归初识和实例分析