Javascript中bind函数和new对于this的影响分析

1. 问题描述

js 复制代码
function fn(name) {
  this.name = name;
}
const obj = {}
const fn1 = fn.bind(obj);
const instance = new fn1("abc");
console.log(instance.name);
console.log(obj.name);

上面这段代码的输出结果是:

js 复制代码
abc
undefined

在这段代码中我们首先声明了一个函数 fn, 函数内部将参数 name 赋值给 this 的 name 属性;随后将变量 fn 通过 bind 函数绑定了一个空对象 obj;之后通过 new fn1("abc") 创建了实例 instance; 通过打印,可以发现 instance 的 name 属性是实例化时传入的参数 "abc",而 obj 的 name 属性不存在。

根据这个现象我们可以推断,在 fn 中获取到的 this 是 instance,而不是通过 bind 函数绑定的 obj。因此我们可以得到结论,new 绑定对于 this 指向的优先级要高于 bind 函数。

2. 原因解释

想要知道其中的原因,必然要知道 bind 的实现原理。参考 core-js 对 bind 函数的 polyfill(github.com/zloirock/co... ),我们可以对 bind 函数实现原理有一个大致认识,以下是部分简化后的代码:

js 复制代码
function bind(that /* , ...args */) {
  var F = aCallable(this);
  var Prototype = F.prototype;
  var partArgs = arraySlice(arguments, 1);
  var boundFunction = function bound(/* args... */) {
    var args = concat(partArgs, arraySlice(arguments));
    return this instanceof boundFunction ? construct(F, args.length, args) : F.apply(that, args);
  };
  if (isObject(Prototype)) boundFunction.prototype = Prototype;
  return boundFunction;
};

代码中 aCallable 就是判断传入参数是否可调用,如果是则返回参数本身。construct 函数是将传入的 F 实例化。其它如 arraySlice 、concat、isObject 函数的作用结合函数名都比较好理解。

这里就可以很清晰的看到,bind 函数最终返回了 boundFunction,而在这个函数内部对 this 进行了判断,这里的 this 的值根据我们调用方式的不同就会有差别:

  • 通过 fn.bind(obj)(xxx) 直接调用

此时 bind 函数获取到的 that 参数为 obj,而 bind 函数中的 this 对象则是 fn。fn.bind(obj) 返回了 boundFunction 函数,相当于调用 boundFunction(xxx),这时 boundFunction 函数没有显示的调用对象,因此 this 指向全局对象。

  • 通过 new fn.bind(obj)(xxx) 形式调用

fn.bind(obj) 函数返回的是函数 boundFunction,这里通过 new 调用,所以相当于 new boundFunction(xxx),那么显然在 boundFunction 中获取到的 this 就是 boundFunction 实例化后的对象。

我们在前面的代码中执行了 new fn.bind(obj)("abc"),也就相当于执行 new boundFunction(obj)("abc")。

我们继续看 boundFunction 中 return 的内容。这一部分代码首先对 this instanceof boundFunction 进行了判断,又可以分两种情况讨论:

  • 如果我们是直接调用的话 this 指向全局对象,那么显然判断条件不成立,因此会走入 F.apply(that, args),这里的 that 根据前文分析是传入 bind 的参数 obj 对象,这种形式就是我们将函数 F 的 this 显式绑定了对象 obj。

  • 如果我们通过 new 进行调用,this 指向 boundFunction 的实例对象,那么判断条件成立,执行 construct(F, args.length, args),相当于 new F(...args),这里的 F 就是 bind 函数获取到的 this,也就是 fn 函数。因此最终我们执行的实际上是 new fn(xxx),很明显此时我们在 fn 函数中获取到的 this 就是 fn 实例化后的对象,而非我们在 bind 中传递的参数 obj。

3. 小结

我们在同时用 new 和 bind 函数去改变 this 指向时,new 对 this 的影响优先级要高于 bind 函数。这是由于在 bind 函数中我们返回了一个新函数 boundFunction,并且在这个函数中对 this instanceof boundFunction 进行了判断。调用方式的不同会导致判断结果的不同,最终导致了 new 对 this 指向的影响优先级高于 bind 函数。

相关推荐
我命由我1234519 分钟前
访客系统形式(有用户概念、无用户概念)
java·开发语言·前端·javascript·python·产品运营·产品经理
key_3_feng34 分钟前
评估与对齐:Agent 自我进化的护栏
前端·数据库·agent
程序员大阳1 小时前
副队长JavaScript教程(65)-详解JSON:轻量级数据交换格式
javascript·json·序列化·反序列化·stringify·parse
LaughingZhu1 小时前
Product Hunt 热榜 2026-10-30:Empacer、Scape、Floot in ChatGPT
java·前端·数据库·人工智能·chatgpt·notion
Lank_M1 小时前
抠图结果缩放后边缘发脏,该怪的不是插值
前端
jerrywus1 小时前
Skill、MCP、Workflow、Rules、Memory 有什么区别?拿几次真实开发任务讲清楚
前端·agent·claude
补码缩写2 小时前
canvas 与 sharp 缩放透明图:默认预乘,非预乘得拆通道
前端
静默回滚2 小时前
抠图 PNG 缩小再放大,边缘又糊又白是两件事
前端
用户11977079480732 小时前
GitHub 电商开源项目分享:用 sharp 批量出饰品主图,试了裁剪、细节图和色彩配置文件三个坑
前端·node.js
deli0072 小时前
地图定位为什么偏了 500 米?GPS 与火星坐标实测
前端