前端面试题 - 可以手写一个new()吗?
前端面试遇到的题目,手写实现一个类似于 new 的函数,或者 new 的实现原理。
首先了解下 new 执行的大致原理:
1.创建新对象。
2.对象的原型与构造函数挂钩。
3.将对象作为上下文,执行构造函数。
4.判断构造函数是否有返回对象或函数,有则返回,没有则返回创建的对象。
// 模拟 new
function myNew (constructor, ...args) {
// 步骤1:创建新的对象
let target = {}
// 步骤2:将该对象的 __proto__ 与构造函数的 prototype 进行挂钩。
//targe.__proto__ = constructor.prototype
Object.setPrototypeOf(target, constructor.prototype)
// 步骤3:将该对象作为构造函数的上下文,执行构造函数,并拿到构造函数的返回值。
const Res = constructor.apply(target, args)
// 构造函数若返回对象,则 return 返回的对象
if (Res instanceof Object) return Res
// 否则 return 该对象
return target
}
function Person (name) {
this.name = name || '我是名字'
}
Person.prototype.sayName = function () {
console.log('sayName >>>', this.name)
}
let p1 = myNew(Person, '老李')
p1.sayName() // sayName >>> 老李
在网上看到另一种写法,也记录下。
function create () {
// 1. 创建新的对象。
let obj = new Object()
// 2.利用 shift 拿到 arguments 的第一个参数,也就是构造函数。
const Func = [].shift.call(arguments)
// 3.将新对象的 __proto__ 与构造函数的 prototype 挂钩。
//obj.__proto__ = Func.prototype
Object.setPrototypeOf(obj, Func.prototype)
// 4.将新对象作为上下文执行构造函数。
const Res = Func.apply(obj, arguments)
// 5.判断返回值是否为对象,若是对象则返回该对象,否则返回新对象。
return Res instanceof Object ? Res : obj
}
function Person (name) {
this.name = name || '我是名字'
}
Person.prototype.sayName = function () {
console.log('sayName >>>', this.name)
}
let p1 = create(Person, '老李')
p1.sayName() // sayName >>> 老李