[JavaScript模拟实现]new操作符

251 阅读1分钟

要创建构造函数的实例,应使用 new 操作符,new一个对象的过程如下:

  1. 在内存中创建一个新对象。
  2. 这个新对象内部的[[Prototype]]特性被赋值为构造函数的 prototype 属性。
  3. 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)。
  4. 执行构造函数内部的代码(给新对象添加属性)。
  5. 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。

解释下第5点:

function Person(name, age) {
    this.name = name
    this.age = age
    return {
        job: 'Software Engineer' //返回非空对象
    }
}
let person1 = new Person("小刘", 18)
console.log(person1) //{job: "Software Engineer"}
console.log(person1.name) //undefined 

function Person(name, age) {
    this.name = name
    this.age = age
}
console.log(person1) //Person {name: "小刘", age: 18},返回刚创建的对象
console.log(person1.name) //小刘

也就是说,原始类型和空对象返回刚创建的对象,其他情况返回return 的对象。

模拟实现

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

function createNew(con) {
    //创建一个空对象并连接到原型,result 可以访问构造函数原型中的属性
    let result = Object.create(con.prototype)
    //保存没有 arguments 第一个参数的数组副本,相当于参数从第1位开始,第0位空出来了
    let args = [].slice.call(arguments, 1)
    //绑定this实现继承,result 可以访问到构造函数中的属性
    let conResult = con.apply(result, args)
    //返回对象的判定,这里不用 instanceof 是因为 Objecct.create(null) 没有原型链
    return ((typeof conResult === 'Object' && conResult !== null) || typeof conResult === 'function') ? conResult : result
}

let person = createNew(Person, '小刘', 18, 'Software Engineer')
console.log(person) //Person {name: "小刘", age: 18, job: "Software Engineer"}

参考:

javascript高级程序设计第四版

深度解析 new 原理及模拟实现

重学 JS 系列:聊聊 new 操作符

面试官问:能否模拟实现JS的new操作符

javascript模拟new的实现