前言
new
运算符是我们在用构造函数创建实例的时候使用的,本文来说一下 new
运算符的执行过程和如何自己实现一个类似 new
运算符的函数。
new 运算符的运行过程
new
运算符的主要目的就是为我们创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例(比如箭头函数就没有构造函数,所以是不能 new
的)。new
操作符的执行大概有以下几个步骤:
__proto__
链接到构造函数的 prototype
对象(每一个用户定义函数都有一个 prototype
属性指向一个对象,该对象有一个 constructor
属性指向该函数),让我们的公共属性和方法可以从原型上继承,不用每个实例都创建一次。 this
的上下文,执行构造函数,构造函数的执行让我们配置对象的私有属性和方法。this
。我么可以用代码简单表示上面的逻辑:
function new_ (constr, ...rests) { var obj = {}; obj.__proto__ = constr.prototype; var ret = constr.apply(obj, rests); return isPrimitive(ret) ? obj : ret; //判断构造函数的返回值是否为对象,不是则直接返回创建的obj对象 }
new 的实现
上面讲了 new
运算符的执行过程,下面我们来自己动手实现一个 new
运算符。
function new_(constr, ...rests) { if (typeof constr !== "function") { throw "the first param must be a function"; } new_.target = constr; var obj = Object.create(constr.prototype); var ret = constr.apply(obj, rests); var isObj = typeof ret !== null && typeof ret === "object"; var isFun = typeof ret === "function"; //var isObj = typeof ret === "function" || typeof ret === "object" && !!ret; if (isObj || isFun) { return ret; } return obj; } function Person(name, age) { this.name = name; this.age = age; } Person.prototype.say = function () { console.log(this.name); }; var p1 = new_(Person, 'clloz', '28') var p2 = new_(Person, 'csx', '31') console.log(p1); //Person {name: "clloz", age: "28"} p1.say(); //clloz console.log(p2); //Person {name: "csx", age: "31"} p2.say(); //csx console.log(p1.__proto__ === Person.prototype); //true console.log(p2.__proto__ === Person.prototype); //true