前端手写: new操作符

手写 new 操作符

1. new 操作符的工作原理

javascript 复制代码
// new 操作符做了以下4件事:
// 1. 创建一个空对象
// 2. 将这个空对象的原型指向构造函数的 prototype
// 3. 将构造函数的 this 绑定到这个新对象
// 4. 执行构造函数
// 5. 返回这个新对象(如果构造函数没有返回对象,则返回 this)

function Person(name, age) {
  this.name = name;
  this.age = age;
}

// 使用 new
const p1 = new Person('张三', 25);

2. 手写 myNew 函数

2.1 基础版本

javascript 复制代码
function myNew(constructor, ...args) {
  // 1. 创建一个新对象
  const obj = {};
  
  // 2. 将对象的原型指向构造函数的 prototype
  obj.__proto__ = constructor.prototype;
  // 或者使用:Object.setPrototypeOf(obj, constructor.prototype);
  
  // 3. 将构造函数的 this 绑定到新对象,并执行构造函数
  const result = constructor.apply(obj, args);
  
  // 4. 判断构造函数返回值类型
  // 如果构造函数返回一个对象,则返回这个对象
  // 否则返回新创建的对象
  return result instanceof Object ? result : obj;
}

3. 面试常考版本(精简)

javascript 复制代码
// 面试时能写出的最简版本
function myNew(Con, ...args) {
  const obj = Object.create(Con.prototype);
  const result = Con.apply(obj, args);
  return result instanceof Object ? result : obj;
}

4. 实现原理详解

javascript 复制代码
// 详细解释每一步
function explainNew(constructor, ...args) {
  console.log('1. 获取构造函数:', constructor);
  
  // 步骤1:创建空对象
  console.log('2. 创建一个空对象');
  const obj = {};
  
  // 步骤2:设置原型链
  console.log('3. 设置对象的原型为构造函数的 prototype');
  console.log('   构造函数 prototype:', constructor.prototype);
  obj.__proto__ = constructor.prototype;
  console.log('   新对象的 __proto__:', obj.__proto__);
  
  // 步骤3:执行构造函数
  console.log('4. 执行构造函数,绑定 this 到新对象');
  console.log('   构造函数参数:', args);
  const result = constructor.apply(obj, args);
  console.log('   构造函数返回值:', result);
  console.log('   新对象当前状态:', obj);
  
  // 步骤4:判断返回值
  console.log('5. 判断构造函数返回值类型');
  const shouldReturnResult = result && (typeof result === 'object' || typeof result === 'function');
  console.log('   应该返回构造函数返回值吗?', shouldReturnResult);
  
  return shouldReturnResult ? result : obj;
}

// 测试
function Demo(name) {
  this.name = name;
  this.createdAt = new Date();
}
const demo = explainNew(Demo, '测试');

5. 常见面试问题

Q1: new 操作符做了什么?

A:

  1. 创建一个新对象
  2. 将这个对象的原型指向构造函数的 prototype
  3. 将构造函数的 this 绑定到这个新对象,并执行构造函数
  4. 如果构造函数返回一个对象,则返回这个对象;否则返回新创建的对象

Q2: 手写 new 操作符的思路?

A:

javascript 复制代码
function myNew(Con, ...args) {
  // 1. 创建对象,设置原型
  const obj = Object.create(Con.prototype);
  // 2. 执行构造函数
  const result = Con.apply(obj, args);
  // 3. 判断返回值
  return result instanceof Object ? result : obj;
}

Q3: 构造函数返回基本类型会怎样?

A: 如果构造函数返回基本类型(string, number, boolean, null, undefined),这个返回值会被忽略,new 操作符会返回新创建的对象。

Q4: 构造函数返回对象会怎样?

A: 如果构造函数返回一个对象(包括数组、函数),那么这个对象会作为 new 表达式的结果,而不是新创建的对象。

Q5: 箭头函数能用 new 调用吗?

A: 不能。箭头函数没有自己的 this,也没有 prototype 属性,所以不能作为构造函数使用。

6. 总结

手写 new 的核心步骤

  1. 创建对象:创建一个新对象
  2. 设置原型 :将对象的 __proto__指向构造函数的 prototype
  3. 绑定 this :使用 applycall将构造函数的 this 绑定到新对象
  4. 执行构造函数:传入参数执行
  5. 返回结果:判断构造函数返回值,如果是对象则返回,否则返回新对象

一句话总结:new 操作符就是创建一个新对象,将其原型指向构造函数的 prototype,然后以这个对象为 this 执行构造函数,最后根据构造函数返回值决定返回什么。

相关推荐
爱勇宝3 小时前
鸿蒙生态的下半场:开发者不只要能开发,还要能赚钱
android·前端·程序员
IT_陈寒7 小时前
SpringBoot这个自动配置坑我跳了三次
前端·人工智能·后端
kyriewen7 小时前
我用 AI 一周写完了整个项目,上线第一天就崩了——这是我踩过最贵的 5 个坑
前端·javascript·ai编程
牧艺7 小时前
从零到协同:构建类飞书在线文档系统的五个技术重难点
前端·人工智能
红尘散仙8 小时前
想写一个像样的终端 App?试试把 React 的开发体验搬进 Rust TUI
前端·rust
袋鼠云数栈UED团队9 小时前
一套 Spec-First 的 AI 编程工作流
前端·人工智能
袋鼠云数栈前端9 小时前
一套 Spec-First 的 AI 编程工作流
前端·ai+
angerdream9 小时前
Android手把手编写儿童手机远程监控App之vue3 路由守卫
前端
不服老的小黑哥9 小时前
AI规范驱动编程-harness工程项目实战
前端
vivo互联网技术9 小时前
从 Web 到桌面:基于 Tauri 2.0 + Vue 3 打造 vivo 线下门店「大头贴」拍照体验系统
前端·rust