JTangming/blog

实现 new 操作符

Opened this issue · 2 comments

实例代码:

function Person(name){ 
  this.name = name;
} 
Person.prototype.getName = function() {
    return this.name;
}

var p1 = new Person('Dan');

console.log(p1); // Person {name: "Dan"}
console.log(p1.__proto__ === Person.prototype); // true

new 操作符实现了如下的功能:

  • 创建一个新对象
  • 新对象的原型指向构造函数的原型对象性,即继承构造函数的原型
  • 改变构造函数 this 的指向到新建的对象,并执行构造函数
  • 判断返回的值是不是一个对象,若是则返回这个对象,否则返回新对象

构造函数如果返回基本类型,则还是会返回原来的 this (新对象)。如果返回的是引用类型,则返回该返回值。(可以自己在上面例子加上代码验证一下)

new 操作符的模拟实现

function createNew(func, ...args) {
    let obj = {};
    // 将空对象指向构造函数的原型链
    Object.setPrototypeOf(obj, func.prototype);
    // obj 绑定到构造函数上,便可以访问构造函数中的属性
    let result = func.apply(obj, args);
    // 如果返回的 result 是一个对象则返回该对象,new 方法失效,否则返回 obj
    return result instanceof Object ? result : obj;
}

Object.setPrototypeOf()是ECMAScript 6最新草案中的方法,相对于 Object.prototype.proto ,它被认为是修改对象原型更合适的方法

写个测试用例:

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

let test = createNew(Test, 'Dan', 20);
console.log(test.name); // Dan
console.log(test.age); // 20

也就是说JS的实例是可以更改构造函数的prototype的。。。(通过__proto__)
刚刚自己写了个例子测试,真的吓一跳