关于js new一个对象时做了什么并怎么模拟一个new

109 阅读1分钟

new做了什么

先看一下mdn的解释吧

  1. 创建一个空的简单 JavaScript 对象(即  {} );
  2. 为步骤 1 新创建的对象添加属性  __proto__ ,将该属性链接至构造函数的原型对象;
  3. 将步骤 1 新创建的对象作为 this 的上下文;
  4. 如果该函数没有返回对象,则返回 this

感觉还算好理解,毕竟学过new对象时this指向的就是新创建的对象,原型链又是一层一层往上的。

既然这样,我们来模拟一下new吧

思路:写一个函数来模拟new,传入的第一个参数是构造函数,之后的参数是原本new时传入的参数

// 第一版代码
function objectFactory() {
    var obj = {},  //这里用var obj = {}也是一样的
    //Constructor = [].shift.call(arguments);  //讶羽大佬的代码
    Constructor = arguments[0];  //第一个参数是构造函数
    obj.__proto__ = Constructor.prototype;  //传承作用域链
    //Constructor.apply(obj, arguments);  //讶羽
    Constructor.apply(obj, Array.from(arguments).slice(1));  //改变指向
    return obj;
};

Constructor = [].shift.call(arguments); 这操作对于我来说真是有点难以理解了,arguments不是数组,又需要把arguments的第一项抽出来,不然apply的时候会多出来一个参数。这一步就完成了。。

实验一下

function FatOtaku (name, age) {
    this.name = name;
    this.age = age;
    this.habit = 'Games';
}

FatOtaku.prototype.strength = 60;

FatOtaku.prototype.sayYourName = function () {
    console.log('I am ' + this.name);
}

function objectFactory() {
    var obj = new Object(),
    Constructor = arguments[0];
    obj.__proto__ = Constructor.prototype;
    Constructor.apply(obj, Array.from(arguments).slice(1));
    return obj;
};

var person = objectFactory(FatOtaku, 'Kevin', '18')
var person1 = new FatOtaku('Kevin1', '28')

console.log(person.name) // Kevin
console.log(person1.name) // Kevin1
console.log(person.age) // 18
console.log(person1.age) // 28
console.log(person.habit) // Games
console.log(person1.habit) // Games
console.log(person.strength) // 60
console.log(person1.strength) // 60

person.sayYourName(); // I am Kevin
person1.sayYourName(); // I am Kevin1