真实面经题目 · 原创解析
new 关键字的运行流程?实现一个自己的 new
这题考察 new 的四步语义、原型链绑定、this 绑定和构造函数返回值规则,手写实现要覆盖返回对象的特殊分支。
真实面经题目 · 原创解析
这题考察 new 的四步语义、原型链绑定、this 绑定和构造函数返回值规则,手写实现要覆盖返回对象的特殊分支。
new 的执行流程可以按四步回答:创建一个新对象;把新对象的原型指向构造函数的 prototype;用这个新对象作为 this 执行构造函数并传入参数;根据构造函数返回值决定结果。如果构造函数显式返回对象或函数,new 表达式返回这个引用值;如果返回基本类型或没有返回值,就返回最初创建的新对象。手写 myNew 时可以用 Object.create(Constructor.prototype) 创建实例,再用 apply 执行构造函数,最后判断返回值是不是引用类型。
new 不是简单调用函数,而是创建一个能通过原型链访问构造函数 prototype 的实例对象,并把构造函数内部的 this 绑定到这个实例上。
实例本身通常只放实例属性,共享方法放在 Constructor.prototype 上。new 建立实例到 prototype 的原型链接,所以实例可以沿原型链找到方法。
构造函数执行时,this 指向新对象。构造函数里写 this.name = name,本质是在新对象上添加或修改实例属性,而不是写到全局对象或 prototype。
构造函数返回对象或函数时,new 的结果会被这个返回值替代;返回 string、number、boolean、symbol、bigint、null、undefined 时,会忽略该返回值,仍返回实例。
箭头函数没有自己的 this,也没有可用于构造的 prototype,不能被 new。class 必须通过 new 调用,直接用 apply 模拟 class 构造会报错,面试手写通常针对普通函数构造器。
function myNew(Constructor, ...args) {
if (typeof Constructor !== "function") {
throw new TypeError("Constructor must be a function");
}
const instance = Object.create(Constructor.prototype);
const result = Constructor.apply(instance, args);
const isObject = result !== null && (typeof result === "object" || typeof result === "function");
return isObject ? result : instance;
} 箭头函数没有自己的 this 绑定,也没有作为构造器使用的 prototype,因此没有 [[Construct]] 能力,不能创建实例。
null 虽然 typeof 是 object,但不是有效引用返回值。new 会忽略它,返回创建出来的实例对象。
{} 的原型默认是 Object.prototype;Object.create 可以显式指定原型。手写 new 需要把实例原型指定为 Constructor.prototype。
new 绑定优先于 bind 指定的 this。用 new 调用绑定函数时,this 指向新实例,但 bind 预置的参数仍然会参与调用。