You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript引擎执行包装函数步骤及包装函数this指向解析

注:示例代码存在一处笔误,计算执行时长的语句中stop.getTime()应为end.getTime(),否则运行时会抛出stop is not defined的引用错误,以下分析基于修正后的代码展开。

一、包装函数的完整执行步骤

JS引擎执行这段代码的流程完全遵循ECMAScript标准的执行上下文、作用域规则,可拆为3个核心阶段:

  • 全局上下文初始化阶段
    引擎先扫描全局范围内的声明做变量提升:function声明的profile会被直接初始化为函数对象,var声明的profiledMax初始化为undefined,同时profile的词法作用域绑定为全局作用域。
  • profile函数调用阶段
    执行var profiledMax = profile(Math.max, 'Math.max')时,引擎为profile创建新的执行上下文并入栈:
    1. 绑定形参:func指向传入的原生Math.max函数,funcName绑定为字符串'Math.max'
    2. 创建内部要返回的匿名函数,这个匿名函数的内部属性[[Environment]]会指向当前profile上下文的词法环境——这就是闭包的核心:哪怕后续profile执行完出栈,只要这个匿名函数还被引用,它就能一直访问到func和funcName两个形参的值,这部分内存不会被垃圾回收
    3. profile执行完毕,把返回的匿名函数赋值给全局变量profiledMax,自身执行上下文出栈
  • 包装后函数调用阶段
    执行profiledMax.call(Math, 1, 2)时,引擎为返回的匿名闭包创建执行上下文并入栈:
    1. 由于用了call显式绑定,这个匿名函数执行时的this被设置为传入的Math对象,类数组参数arguments绑定为[1, 2]
    2. 逐行执行匿名函数内部逻辑:
      • 初始化start为当前时间的Date实例
      • 执行func.apply(this, arguments):把闭包当前的this、参数透传给闭包保存的原函数Math.max,执行后拿到返回值2,赋值给returnVal
      • 初始化end为原函数执行完成后的当前时间Date实例
      • 计算时间差得到执行时长
      • 打印耗时日志
      • 把returnVal作为匿名函数的返回值返回
    3. 匿名函数执行完毕,执行上下文出栈,控制权回到全局上下文。

二、被包装函数延后执行时的this判定规则

首先明确核心原则:JS里所有函数的this都是在实际执行的瞬间才完成绑定的,和函数定义在哪、被赋值给哪个变量、被传递过多少次没有任何关系,判定时按优先级从高到低匹配即可,不存在例外:

  1. new绑定(最高优先级):如果函数是通过new关键字调用的,不管之前做过什么绑定,this都指向new新创建的实例对象
  2. 显式绑定:如果函数通过call/apply/bind指定了this,this就指向传入的第一个参数;如果传入的是null/undefined,非严格模式下会自动替换为全局对象(浏览器为window,Node.js为globalThis),严格模式下保留原值。示例里的profiledMax.call(Math, 1,2)就属于这类,所以闭包内的this是Math对象
  3. 隐式绑定:如果函数作为对象的属性,通过对象.函数()的形式调用,this指向点前面的那个对象。比如写const testObj = { getMax: profiledMax }; testObj.getMax(1,2),那profiledMax执行时的this就指向testObj
  4. 默认绑定(最低优先级):如果函数不符合以上三种调用方式,直接独立运行,非严格模式下this指向全局对象,严格模式下this为undefined

你写的这个profile是典型的函数装饰器实现,里面用func.apply(this, arguments)就是为了把包装函数收到的this和参数原封不动透传给原函数,保证包装后的函数和原函数的this行为完全一致,不会因为加了耗时统计逻辑就改变原函数的调用规则。


内容的提问来源于stack exchange,提问作者sens

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 04:54:37