默认调用 对象调用 call apply调用
1.函数在调用时,JavaScript会默认给this绑定一个值; 2.this的 绑定和定义的位置(编写的位置) 没有关系; 3.this的绑定和调用方式以及调用的位置有关系; 4.this是在运行时被绑定的;
判断this
现在我们可以根据优先级来判断函数在某个调用位置应用的是哪条规则。可以按照下面的
顺序来进行判断:
- 函数是否在new 中调用(new 绑定)?如果是的话this 绑定的是新创建的对象。
var bar = new foo()
- 函数是否通过call、apply(显式绑定)或者硬绑定调用?如果是的话,this 绑定的是
指定的对象。
var bar = foo.call(obj2)
- 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this 绑定的是那个上
下文对象。
var bar = obj1.foo()
- 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到undefined,否则绑定到
全局对象。
var bar = foo()
就是这样。对于正常的函数调用来说,理解了这些知识你就可以明白this 的绑定原理了。
不过…凡事总有例外。
如果要判断一个运行中函数的this 绑定,就需要找到这个函数的直接调用位置。找到之后
就可以顺序应用下面这四条规则来判断this 的绑定对象。
- 由new 调用?绑定到新创建的对象。
- 由call 或者apply(或者bind)调用?绑定到指定的对象。
- 由上下文对象调用?绑定到那个上下文对象。
- 默认:在严格模式下绑定到undefined,否则绑定到全局对象。
一定要注意,有些调用可能在无意中使用默认绑定规则。如果想“更安全”地忽略this 绑
定,你可以使用一个DMZ 对象,比如ø = Object.create(null),以保护全局对象。
ES6 中的箭头函数并不会使用四条标准的绑定规则,而是根据当前的词法作用域来决定
this,具体来说,箭头函数会继承外层函数调用的this 绑定(无论this 绑定到什么)。这
其实和ES6 之前代码中的self = this 机制一样。
在JavaScript中,this
的行为由语言规范定义,而V8等引擎通过内部机制实现这些规则。以下是this
的关键点及引擎处理的解析:
一、this
的绑定规则
-
默认绑定
- 非严格模式:全局对象(如
window
或global
)。 - 严格模式:
undefined
。
function foo() { console.log(this); } foo(); // 全局对象(非严格)或 undefined(严格)
- 非严格模式:全局对象(如
-
隐式绑定
- 函数作为对象方法调用时,
this
指向该对象。
const obj = { foo() { console.log(this); } }; obj.foo(); // obj
- 函数作为对象方法调用时,
-
显式绑定
- 使用
call
、apply
或bind
强制设置this
。
function foo() { console.log(this); } foo.call({ a: 1 }); // { a: 1 }
- 使用
-
new
绑定- 构造函数中,
this
指向新创建的对象实例。
function Foo() { this.x = 1; } const instance = new Foo(); // this → instance
- 构造函数中,
-
- 词法作用域决定
this
,继承外层非箭头函数的this
。
const obj = { foo: () => console.log(this), // 外层作用域的this(如全局对象) }; obj.foo();
- 词法作用域决定
二、V8引擎的内部处理
-
执行上下文与
this
的解析- 每次函数调用会创建**执行上下文**,其中包含
this
的值。 - 引擎根据调用方式(方法、构造函数等)动态确定
this
。
- 每次函数调用会创建**执行上下文**,其中包含
-
词法分析阶段的处理
- 箭头函数在解析时捕获外层
this
,存储为词法环境的一部分。 - 普通函数在调用前
this
未确定,依赖调用时的上下文。
- 箭头函数在解析时捕获外层
-
优化策略
- 内联缓存(Inline Caching):对频繁调用的方法缓存
this
的类型,减少查找开销。 - 隐藏类(Hidden Classes):优化对象属性的访问,间接加速
this
相关操作。
- 内联缓存(Inline Caching):对频繁调用的方法缓存
-
严格模式的处理
- 函数内部若启用严格模式(通过
"use strict"
),引擎会将未绑定的this
设为undefined
,而非默认的全局对象。
- 函数内部若启用严格模式(通过
-
显式绑定的底层实现
call
/apply
直接修改调用帧中的this
值。bind
生成包裹函数,闭包保存预设的this
,调用时直接传递。
三、宿主环境的影响
- 浏览器/DOM事件:事件处理函数中的
this
通常指向触发元素,由DOM API设置,非引擎行为。 - Node.js模块:顶级
this
指向模块的exports
对象,而非全局对象。
四、总结
- 动态性:普通函数的
this
在调用时动态确定,依赖调用方式。 - 词法性:箭头函数的
this
在定义时静态捕获,不受调用方式影响。 - 引擎优化:V8通过内联缓存、隐藏类等技术高效管理
this
,提升性能。 - 规范遵循:严格模式、显式绑定等行为严格遵循ECMAScript标准。
理解this
需结合语言规范与引擎实现机制,同时注意宿主环境(如浏览器)的扩展行为。