实现关键字new
要实现new,第一步得知道它做了什么....
# new做了什么
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例
当我们使用new的时候,他做了什么:
- 他返回了一个全新对象。
- 将这个对象的原型对象指向构造函数的原型属性,从而继承原型上的方法
- 将this指向新创建的对象,执行构造函数中的代码,以获取私有属性
- 如果该函数没有返回对象类型 Object(包含Function, Array, Date, RegExg, Error),则返回新创建的对象。
function Dog (name) {
this.name = name;
this.voice = '汪汪';
}
Dog.prototype.speed = 100;
Dog.prototype.say = function () {
console.log(this.voice);
}
const dog = new Dog('ww');
console.log(dog.name) // ww
console.log(dog.voice) // 汪汪
console.log(dog.speed) // 100
dog.say(); // 汪汪
实例dog
- 可以访问原型属性和方法
- 可以访问构造函数的属性
# 语法
// constructor 类或函数
// arguments 参数,可选
new constructor[([arguments])]
# 尝试
我们用函数来模拟
function MyNew(fn,...arg) {
const res = {} // 声明对象
res.__proto__ = fn.prototype //指向原型属性
fn.apply(res,arg) // 改变this指向
return res;
}
//简单运行下
let dog = MyNew(Dog,'ww');
console.log(dog.name) // ww
console.log(dog.voice) // 汪汪
console.log(dog.speed) // 100
dog.say(); // 汪汪
基本功能实现了,我们来完善下。
//上面的实现中,我们试试Array类型
var arr = MyNew(Array)
console.log(arr)
/**
Array {}
__proto__: Array(0)
*/
原因在于有些基本类型不返回对象,我们需要加个判断,构造函数返回不是对象的,直接返回其执行结果。
function MyNew(fn,...arg) {
const res = {} // 声明对象
res.__proto__ = fn.prototype //指向原型属性
const ret = fn.apply(res,arg) // 改变this指向
return ret&& (typeof ret === 'object'||typeof ret === 'function') ? ret : res;
}
var arr = MyNew(Array)
/**
[]
length: 0
__proto__: Array(0)
*/
# 更简洁的实现
function myNew(Fn, ...args) {
//1.创建一个空对象,并将对象的__proto__指向构造函数的prototype 这里我两步一起做了
const res = Object.create(Fn.prototype);
//2.将构造函数中的this指向obj,执行构造函数代码,获取返回值
const ret = Fn.apply(res, args);
//3.判断返回值类型
return ret&& (typeof ret === 'object'||typeof ret === 'function') ? ret : res;
}