bind 方法通过闭包保存 thisarg 和预设参数,并在调用时用 apply 强制绑定 this;new 调用时让渡 this 优先级以支持构造函数语义;null/undefined 在非严格模式下被 apply 自动转为 window;原型链通过 object.create 继承确保 new 实例可访问原函数原型方法。

bind 方法保留 this 引用,靠的不是“记忆”或“缓存”,而是**在创建新函数时,把指定的 thisArg 封进闭包,并在每次调用新函数时,强制用 apply(或 call)将它设为执行上下文**。这个过程不依赖运行时动态推断,而是由 bind 返回的函数内部逻辑硬编码决定。
核心机制:闭包 + apply 动态绑定
当你调用 fn.bind(obj, 1),返回的并不是原函数的拷贝,而是一个新函数(常称 boundFn)。这个新函数体内始终持有一个对 obj 的引用(通过闭包捕获),并在自己被调用时,用 fn.apply(obj, [...]) 显式触发执行——this 值由此被锁定为 obj,不受调用方式影响。
- 闭包保存了你传入的
thisArg(比如 obj)和预设参数(如 1),这些值在 boundFn 生命周期内一直可用 - 每次调用 boundFn,它内部都主动调用
原函数.apply(绑定的 thisArg, 合并后的参数) - 即使你把 boundFn 赋给全局变量、传进 setTimeout 或作为事件回调,apply 这一步仍会把 this 指向最初绑定的对象
new 调用的特殊处理:this 优先级让渡
如果 boundFn 被 new 调用(new boundFn()),JavaScript 引擎会忽略闭包里存的 thisArg,转而让 this 指向新生成的实例。这是为了保证构造函数语义正确——否则无法继承原型、无法用 this 初始化实例属性。
- boundFn 内部会检测
this instanceof boundFn - 为真时,直接
new 原函数(...),此时 this 是新实例,且 boundFn.prototype 已被设为原函数 prototype 的副本,确保原型链连通 - 为假时,才走 apply 绑定路径,使用闭包中保存的 thisArg
为什么 null/undefined 在非严格模式下变成 window?
这不是 bind 自己做的转换,而是 apply(或 call)规范行为:当传入的 thisArg 是 null 或 undefined,且当前非严格模式,apply 会自动把它们替换成全局对象(浏览器中是 window)。bind 只是把你的参数原样传给 apply,后续转换由底层引擎完成。
- 严格模式下,null/undefined 会被原封不动传给函数内部的 this
- 原始值(如 1、'abc')会被临时包装成对象(Number、String),但仅限非严格模式;严格模式下保持原始值
- 日常开发建议:只传对象,避免纠结原始值或 null 的隐式转换
原型链继承:让 new 调用真正可行
仅仅处理 new 时的 this 还不够。如果 boundFn.prototype 没有正确指向原函数的 prototype,那么 new boundFn() 创建的实例就无法访问原函数原型上的方法——这会破坏继承关系。
- 标准实现中,会执行
boundFn.prototype = Object.create(originalFn.prototype) - 这样,实例的
__proto__就能顺着 boundFn.prototype → originalFn.prototype 链向上查找 - 这步不可省略,否则 new 出来的对象无法正常使用原型方法











