一、是什么
this这个关键字代表的值为当前函数执行的上下文,大多数情况下this的值取决于函数的调用方式。
this是在运行时进行绑定的,只能在函数内部使用。
二、绑定规则
-
默认绑定
-
在函数体中,非显式或隐式地调用函数时,在严格模式下,函数内的this会被绑定到undefined上,在非严格模式下则会被绑定到全局对象window/global上。
-
function f1(){ console.log(this) } function f2(){ 'use strict' console.log(this) } f1() // window f2() // undefined -
隐式绑定
-
一般通过上下文对象调用函数时,函数体内的this会被绑定到该对象上。
-
function f1(){ console.log(this.a) } var obj = { a: 1; fn: f1 } obj.fn() // 1 // 陷阱1 var f2 = obj.fn f2() // undefined,这里f2()等价window.f2() -
new绑定
-
一般使用new方法调用构造函数时,构造函数内的this会被绑定到新创建的对象即实例对象上。
-
function F() { this.a = 1 } var f = new F() f.a // 1 // 特殊情况 function F1() { this.a = 1 return {} } var f1 = new F1() f1.a // undefined 原因是构造函数中如果return一个对象,则this指向该对象 function F2() { this.a = 1 return 1 } var f2 = new F2() f2.a // 1 原因是构造函数如果return一个基本类型的值,那么this仍指向实例。 -
显式绑定
-
一般通过call/apply/bind方法显示调用函数时,函数体内的this会被绑定到指定参数的对象上。
-
箭头函数
-
在箭头函数中,this指向其所属函数的this或全局作用域。
-
var f = { fn: () => { console.log(this) }} f.fn() // window 因为fn箭头函数并不在函数内,因此指向全局作用域 var f1 = { a: 1, fn: function() { const f = () => { console.log(this) } f() }} f1.fn() // {a: 1, fn:function(){}} 箭头函数指向fn函数的this var f2 = f1.fn f2() // window 此时fn函数的this指向window
三、优先级
-
显式VS隐式
-
var f = { a: 1, fn: function(){ console.log(this.a) } } var obj = {a: 2} f.fn() // 1 f.fn.call(obj) // 2 显式 > 隐式 -
newVS显示
-
function fn(a) { this.a = a } var obj = {} var F = fn.bind(obj) // F的this指向obj F(1) // obj.a = 1 var f = new F(2) // f的this指向了F的实例, f.a === 2 new > 显式 -
箭头VSnew
-
由于箭头函数无法作为构造函数,无法比较。
-
箭头VS显式
-
function fn() { return () => { console.log(this.a) } } const obj1 = {a: 1} const obj2 = {a: 2} const f1 = fn.call(obj1) // 此时箭头函数所属函数的this绑定在obj1 f1() // 1 f1.call(obj2) // 1 箭头函数的this绑定无法被修改 箭头 > 显式
综上得出:new绑定/箭头函数 > 显式绑定 > 隐式绑定 > 默认绑定
参考资料:
- 说说你对Javascript中this对象的理解
- 前端开发核心知识进阶 p3~p13