
JavaScript 中的 this 指向四种绑定规则与优先级详解this是 JavaScript 中一个核心且容易混淆的概念。它的指向不是在定义时确定的而是在调用时确定的即在执行上下文创建时绑定。本文将系统梳理this的四种绑定规则、优先级以及箭头函数的特殊行为。一、四种绑定规则1. 默认绑定独立函数调用当函数以独立函数形式调用不作为对象的方法也不通过call/apply/bind或new调用时this默认绑定到全局对象。浏览器环境windowNode.js 环境global严格模式use strictundefinedfunctionfoo(){console.log(this);// 非严格模式: window; 严格模式: undefined}foo();2. 隐式绑定方法调用当函数作为某个对象的方法被调用时this隐式绑定到该调用对象。如果有多层对象嵌套this指向最近一层的调用对象。constobj{name:Alice,greet(){console.log(this.name);}};obj.greet();// Aliceconstouter{inner:{name:Bob,greet(){console.log(this.name);}}};outer.inner.greet();// Bobthis 指向 inner而非 outer3. 显式绑定主动指定通过call、apply、bind方法可以主动指定函数的this指向这是最灵活的绑定方式。call/apply/bind的区别方法是否立即执行参数传递方式call是第一个参数是this指向后续参数逐个列举apply是第一个参数是this指向第二个参数为数组bind否返回新函数预设this和部分参数返回的新函数永久绑定硬绑定functionsay(age){console.log(${this.name},${age});}constperson{name:Tom};say.call(person,25);// Tom, 25say.apply(person,[25]);// Tom, 25constboundsay.bind(person,25);bound();// Tom, 254. new 绑定构造函数调用当函数通过new关键字调用时作为构造函数this绑定到新创建的实例对象。new操作符内部执行四个步骤创建一个空的新对象。将该新对象的__proto__指向构造函数的prototype。将构造函数的this绑定到这个新对象。如果构造函数没有返回对象则返回这个新对象如果返回了一个对象则返回该对象此时this绑定失败返回的是手动返回的对象。functionPerson(name){this.namename;}constpnewPerson(John);console.log(p.name);// John二、优先级多个规则同时生效时谁为准this绑定的优先级从高到低为new 绑定 显式绑定特别是 bind 隐式绑定 默认绑定functionfoo(){console.log(this.name);}constobj1{name:obj1,foo};constobj2{name:obj2,foo};obj1.foo();// obj1隐式绑定obj1.foo.call(obj2);// obj2显式绑定 隐式绑定constboundfoo.bind(obj1);bound.call(obj2);// obj1bind 硬绑定后无法再被 call/apply 改变constinstancenewbound();// 如果 foo 不是构造函数则报错但若可作为构造函数new 优先级高于 bind新对象会覆盖 bind 绑定的 this注意bind生成的硬绑定函数其this不会被call/apply覆盖但new操作可以覆盖bind的绑定因为new优先级最高。三、箭头函数没有自己的 this 绑定规则箭头函数不绑定自己的this它的this继承自定义时外层词法作用域即箭头函数声明时所在上下文的this并且无法通过call、apply、bind修改。constobj{name:Eve,greet:(){console.log(this.name);// 此处的 this 是外层全局或上层函数的 this不是 obj}};obj.greet();// undefined假设全局没有 name箭头函数与普通函数的核心区别特性普通函数箭头函数this 绑定调用时动态绑定四种规则定义时继承外层 this不可变构造函数能力可以new调用不能new会报错prototype 属性有无arguments 对象有类数组无可用剩余参数...args简写语法function() {}() {}单参数可省略括号特别注意定义对象时的大括号{}不是一个单独的执行环境它依旧处于全局环境中。因此对象字面量内部的方法若使用箭头函数其this仍指向外层作用域通常是window或模块作用域而不是该对象。constobj{name:Test,arrow:()console.log(this.name),normal(){console.log(this.name);}};obj.arrow();// undefinedthis 指向全局obj.normal();// Test四、总结速查表调用方式this 指向普通函数独立调用非严格模式全局对象严格模式undefined对象方法调用该对象最近一层call/apply/bind显式指定的对象bind返回的函数不可再改变new构造函数调用新创建的实例对象箭头函数定义时外层作用域的this不可改变理解this的关键在于记住不看定义在哪只看如何调用。