前提,要明白new出来的实例是什么,包含了哪些内容?
请看一下举例代码↓↓↓↓
function Person(name,age){ this.name = name; this.age = age; } let p =new Person('pxx',18); console.log(p); // 控制台打印 Person {name: "pxx", age: 18} age: 18 name: "pxx" __proto__: constructor: ƒ Person(name,age) __proto__: Object
从上面例子可以得出以下结论:
- new出来的是一个对象
- 对象上有一个__proto__属性,值为Person的原型
- 同时对象上还有构造函数执行的属性
但是还有一点上面例子没有体现,就是假如构造函数本身返回的就是一个对象时的情况,我们稍加改造↓↓↓↓
1.返回值是基本数据类型
function Person(name,age){ this.name = name; this.age = age; return 'test' } let p =new Person('pxx',18); console.log(p); // 控制台打印内容 Person {name: "pxx", age: 18} age: 18 name: "pxx" __proto__: Object
2.返回值是对象
function Person(name,age){ this.name = name; this.age = age; return { name: 'other', age: 20 } } let p =new Person('pxx',18); console.log(p); // 控制台打印如下 {name: "other", age: 20} age: 20 name: "other" __proto__: Object
可以看出,当构造函数返回的是一个对象时,new出来的实例就是函数的返回值。
通过以上分析,我们可以按步骤写出自己的一个new方法
具体步骤如下:
- 建立一个空对象
- 为空对象添加__proto__属性
- 在空对象上执行构造函数
- 判断合法返回值
最终源码如下↓↓↓↓↓↓↓↓↓↓↓↓
function myNew(Fn,...args){ // 1.新建空对象 let o = {}; // 2.对象的__proto__ 属性指向原型 o.__proto__ = Fn.prototype; // 3.以对象为this,执行构造函数 let res = Fn.apply(o,args); // 4.返回合法值 return res instanceof Object? res : o; } let p1 = myNew(Person,'pxx',18); console.log(p1);