实现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:
