new原理及模拟实现
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
举个栗子1
2
3
4
5
6
7
8
9
10
11
12
13function Car(color) {
this.color = color;
}
Car.prototype.start = function() {
console.log(this.color + " car start");
}
var car = new Car("black");
car.color; // 访问构造函数里的属性
// black
car.start(); // 访问原型里的属性
// black car start
可以看出 new 创建的实例有以下 2 个特性
访问到构造函数里的属性
访问到原型里的属性
注意点
ES6新增 symbol 类型,不可以使用 new Symbol(),因为 symbol 是基本数据类型,每个从Symbol()返回的 symbol 值都是唯一的。
1 | Number("123"); // 123 |
new操作符的工作原理
- 一个新对象被创建,它继承自func.prototype。
- 构造函数func 被执行,执行的时候,相应的参数会被传入,同时上下文(this) 会被指定为这个新实例。
- 如果构造函数返回了一个新对象,那么这个对象会取代整个new出来的结果,如果构造函数没有返回对象,
那么new出来的结果为步骤1创建的对象。
1 | 废话不多说,直接上代码 |
DEMO:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23/**
* new2 new关键字的代码实现演示
* @param {function} func 被new的类 (构造函数)
*/
function new2(func) {
// 创建了一个实例对象 o,并且这个对象__proto__指向func这个类的原型对象
let o = Object.create(func.prototype);
// (在构造函数中this指向当前实例)让这个类作为普通函数值行 并且里面this为实例对象
let k = func.call(o);
// 最后再将实例对象返回 如果你在类中显示指定返回值k,
// 注意如果返回的是引用类型则将默认返回的实例对象o替代掉
return typeof k === 'object' ? k : o;
}
// 实验
functionM() { // 即将被new的类
this.name = 'liwenli';
}
let m = new2(M); // 等价于 new M 这里只是模拟
console.log(m instanceof M); // instanceof 检测实例
console.log(m instanceof Object);
console.log(m.__proto__.constructor === M);
Object.create 兼容实现
1 | let obj1 = {id: 1}; |
完整代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23function new2(MyFun, ...list) {
let o = Object.create(MyFun.prototype);
let k = MyFun.call(o, ...list);
return typeof k === 'object' ? k : o;
}
function Car(color, name) {
this.color = color;
this.name = name;
return "new car";
}
Car.prototype.fun=function(){
console.log(this.color,this.name)
}
var obj=new2(Car,123,'小花');
console.log(obj)
console.log(obj.__proto__===Car.prototype);
console.log(Car.prototype.isPrototypeOf(obj))
console.log(Object.prototype.isPrototypeOf(obj))
console.log(obj instanceof Car)
console.log(obj.constructor===Car)
有什么问题?
typeof k === 'object'
如果k为null怎么办?- MyFun传null,undefined怎么办?
1 | function new2(MyFun, ...list) { |