开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 2天,点击查看活动详情
我们经常使用new为一个构造函数创建一个他的实例对象,并且这个实例对象还可以使用构造函数的原型上的属性和方法。内部实现其实可以分为这四步:
- 创建一个空对象(最后一般会返回这个对象)
- 将创建的空对象的
[[prototype]]属性指向构造函数的prototype(可以让实例对象访问到原型上的对象) - 把构造函数的this绑定到新对象上(拿到构造函数的所有属性和方法)
- 最后判断构造函数是否返回了对象,如果返回对象则实例对象就是这个对象,反之实例对象是创建的新对象
写个例子帮助理解
const Mountain = function(){
this.characteristic = 'tall';
// return {}
}
Mountain.prototype.getHeight = function(){
console.log(this.height);
}
const lushan = new Mountain();
lushan.height = '1474'
lushan.getHeight(); // 1474 验证第二步的空对象的`[[prototype]]`属性指向构造函数的`prototype`
console.log(lushan.characteristic); // tall 验证第三步构造函数的this绑定到新对象上
// console.log(lushan); // 构造函数返回对象 实例将无法使用任何构造函数的属性方法(包括原型上的) 验证第四步
简单实现一个new操作符
const mynew = function(constrc, ...args){
// 创建一个对象并把构造函数的prototype属性挂载在对象的[[prototype]]上
const obj = Object.create(constrc.prototype);
// 第一步和第二步也可以这样写
// const obj = {}
// obj.__proto__ = constrc.prototype;
// 把构造函数的this绑定到新对象上
const result = constrc.apply(obj, args);
// 判断构造函数是否返回一个对象
return result instanceof Object ? result : obj;
}
测试
const fun = function(){
this.a = '123';
// return {}
}
fun.prototype.outputa = function(){
console.log(this.a);
}
const obj = mynew(fun);
console.log(obj.a); // 123
obj.outputa(); // 123
console.log(obj.__proto__ === fun.prototype); // true
// console.log(obj); // {} 当构造函数返回一个对象
这样就基本实现了一个简单的new操作符。new操作符也是js中的一种继承。