javascript中new操作符工作原理
今天在复习小红书创建对象一节的时候。里面讲到new操作符的工作原理,但是按照小红书的逻辑来出了点问题。
书中说 new操作符一共三步,按照书里的步骤 代码如下
function Person(name,age,job){ this.name = name this.age = age this.job = job this.sayName = function () { } } var person1 = new Person('Nicholas',29,'Software Engineer') console.log(person1.__proto__ == Person.prototype) // true function New1(fn) { var obj = {} return function () { fn.apply(obj,arguments) return obj } } var person2 = New1(Person)('Greg',27,'Doctor') console.log(person2.__proto__ == Person.prototype) // false
但是明显 通过New1 实例化的person2并没有指向 Person 的原型
所以我们尝试在New1函数中添加一步,即将新建对象指向Person的原型
具体代码如下
function New2(fn) { var obj = {} obj.__proto__ = fn.prototype //将新建对象指向fn的原型 return function () { fn.apply(obj,arguments) return obj } } var person3 = New2(Person)('Alan',18,'singer') console.log(person3.__proto__ == Person.prototype) //true
这样通过New2 实例化的 Person 和 new操作符实例出来的就是基本一致啦
但是当你读到小红书寄生构造函数模式的时候 使用这个New2函数的时候也会遇到坑
function Person2(name,age) { var o = new Object() o.name = name o.age = age o.sayName = function () { console.log(this.name) //顺便提一下 寄生构造函数模式和稳妥构造函数模式区别在于 ,稳妥构造函数模式禁用了this } return o } var person4 = new Person2('Blithe',20) console.log(person4) //{name: "Blithe", age: 20, sayName: ƒ} var person5 = New2(Person2)('Bob',22) console.log(person5) //Person2 {}
这时候通过 New2 实例化的person5 居然是个 空对象,仔细看代码不难发现,我们New2函数返回的是新建对象,但是new操作符返回的是构造函数返回的对象 所以我们的New函数可以多一层判断
function New3(fn) { var obj = {} obj.__proto__ = fn.prototype return function () { var o = fn.apply(obj,arguments) return o?o:n } } var person6 = New3(Person2)('Christina',22) console.log(person6) //{name: "Christina", age: 22, sayName: ƒ}
这样 New3 应该是完整的new操作符 工作流程啦