实现Javascript中的New操作符
new
运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例
new
关键字会进行如下操作:
- 创建一个空的简单JavaScript对象(即{});
- 链接该对象(即设置该对象的构造函数)到另一个对象 ;
- 将步骤1新创建的对象作为this的上下文 ;
- 如果该函数没有返回对象,则返回this。
1 | function Car (make, model, year) { |
const myCar = new Car('toyta', 'AE86', 1987)
按照 new
关键字操作过程实现一个 newObject
函数
1 | function newObject () { |
const myCar2 = newObject(Car, 'nissan', 'civic hatchback', 2019)
hmmmmm myCar
和myCar2
看起来有些不一样, 使用原型链的方法校验一下:
1 | Object.getPrototypeOf(myCar) === Car.prototype // true |
myCar2
没有在Car
的原型链上, 更换创建空obj
的实现方式为:
1 const obj = new Object()
原因是
Object.create(null)
创建的是一个没有原型链链接的空对象,new Object()
类似于Object.create(Object.prototype)
创建的是有原型链链接的空对象,
1 | var a = Object.create(null) |
Object.getPrototypeOf(a) // null
Object.getPrototypeOf(b) === Object.prototype // false
Object.getPrototypeOf(b)
Object.getPrototypeOf(b) === Object.prototype // true
a
是没有原型链链接的空对象,自然访问不到__proto__
属性,没有在原型链上,所以也可以用来做字典,不会有原型链上属性影响。
考虑Car
函数有返回值的情况
我们需要newObject
返回的是一个对象,所以对构造函数返回值进行判定
1 | const ret = constructor.apply(obj, arguments) |
最终版本newObject
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18function newObject () {
const obj = new Object()
const constructor = [].shift.apply(arguments)
obj.__proto__ = constructor.prototype
const ret = constructor.apply(obj, arguments)
return typeof ret === 'Object' ? ret || obj : obj
}
const car1 = new Car('toyta', 'AE86', 1987)
const car2 = newObject(Car, 'toyta', 'AE86', 1987)
Car.prototype.wheels = 4
car1.wheels = 4 // true
car2.wheels = 4 // true
car1 instanceof Car // true
car2 instanceof Car // true
Object.getPrototypeOf(car1) === Object.getPrototypeOf(car2) // true
referrece: