显式绑定中多次bind不会覆盖首次绑定的this,真正生效的始终是第一次bind的对象。例如bound3()仍返回'A'而非'C',因bind返回的是惰性代理函数,每次调用都逐层执行至最内层绑定目标,其[[BoundThis]]不可变。

显式绑定中多次 bind 的核心规则
JavaScript 中,bind 方法返回的新函数具有不可变的 this 绑定,且后续对它再次调用 bind 不会覆盖原始绑定。这是由规范明确规定的:一旦函数被 bind,其内部 [[BoundThis]] 内部槽就被固定,再 bind 只是包装一层新函数,但不会修改或替换已绑定的 this 值。
多次 bind 的实际执行过程
假设:
const obj1 = { name: 'A' };
const obj2 = { name: 'B' };
const obj3 = { name: 'C' };
function foo() { return this.name; }
const bound1 = foo.bind(obj1);
const bound2 = bound1.bind(obj2);
const bound3 = bound2.bind(obj3);
此时 bound3() 仍返回 'A',不是 'C'。
- foo.bind(obj1) 创建函数,内部 [[BoundThis]] = obj1,[[BoundTargetFunction]] = foo
- bound1.bind(obj2) 创建新函数,[[BoundThis]] = obj2,[[BoundTargetFunction]] = bound1(注意:它不“穿透”到 foo)
- bound2.bind(obj3) 同理,[[BoundThis]] = obj3,[[BoundTargetFunction]] = bound2
- 当 bound3() 被调用时,引擎发现它是绑定函数,于是直接执行 [[BoundTargetFunction]](即 bound2),而 bound2 执行时又立即调用它的 [[BoundTargetFunction]](bound1),最终 bound1 拿到自己的 [[BoundThis]](obj1)去调用 foo
为什么不能覆盖?——绑定函数的本质
bind 返回的函数是“惰性代理”,它不重写原始函数的 this,而是在每次调用时强制把预设的 this 值传给目标函数。即使你对 bound1 再 bind,新函数只是“用自己的 this 去调 bound1”,而 bound1 自身逻辑仍是“无视调用时的 this,坚持用 obj1 调 foo”。所以无论嵌套多少层 bind,真正决定 this 的永远是最内层那个 bind 所绑定的对象(即第一次 bind 的对象)。
验证与绕过方式
可通过 console.log(bound3.toString()) 观察到类似 function () { [native code] },说明它是内置绑定函数,无法通过普通方式读取内部绑定值;但可通过以下方式确认行为:
- 打印
bound1.name→ "bound foo" - 检查
bound2.hasOwnProperty('name')→ false(继承自 Function.prototype) - 真正生效的始终是首次 bind 的对象:只有
foo.bind(objX)这一步才设置最终 this
若需动态切换 this,应避免链式 bind,改用 call/apply,或封装可配置的 wrapper 函数。
立即学习“Java免费学习笔记(深入)”;


















