区别
const Base = function () {}
const b1 = new Base()
const b2 = Object.create(Base)
console.log(b1)
console.log(b2)
- 输出结果如下:

- 从上述图片可以看出:
b1.__proto__是一个对象Base {},b2__proto__是一个函数f ()。- 这里提出一个疑问:为什么
b2.__proto__不是Base{}?
Object.create(prototype, descriptors),用原生js实现的代码如下:
Object.create = function (obj) {
const F = function () {}
F.prototype = obj
return new F()
}
- 上述代码做了以下这些事情:
- 新建一个空函数(什么都不干)
- 将对象
obj赋值给空函数F的原型对象prototype- 最终返回一个新对象
- 接下来,说一说
const b1 = new Base()都干了些什么!
- 首先,创建了一个
Object对象b1- 接着,让
b1的__proto__指向了Base.prototype对象- 最后,调用
call强行转换作用环境
const b1 = new Object()
b1.[[Prototype]] = Base.prototype
// 或 b1.__proto__ = Base.prototype
Base.call(b1)
- 接着再看下面的代码
- demo
const Base = function () {
this.a = 1
}
Base.prototype.b = 2
const b1 = new Base()
const b2 = Object.create(Base)
console.log(b1) // Base {a: 1}
console.log(b2) // Function {}
console.log(`b1.a = ${b1.a}, b1.b = ${b1.b}`) // b1.a = 1, b1.b = 2
console.log(`b2.a = ${b2.a}, b2.b = ${b2.b}`) // b2.a = undefined, b2.b = undefined
console.log(b2.__proto__ === Base) // true
console.dir(b2.prototype === Base.prototype) // true
- 输出结果如下:

- 从图中你会发现,属性
a只存在于b1中,而属性b存在于b1的__proto__对象中以及其constructor的prototype对象中,但是, 对于b2来说,b2只存在于constructor的prototype对象中。- 请看下图:


- 先回答这个问题:为什么
b2.__proto__不是Base{}?
- 可从图中看到,
Object.create最终返回的是new F (),根据 discrimination - proto 和 prototype 的区别里面所讲到的规则,b2.__proto__的指向规则是基于创建其的构造函数,因此,其值肯定是f ()非Base {}
- 为什么
b2不能获取到b的值?
- 先看:
b2.__proto__ === Base为true的原因是:
- 因为
b2.__proto__ = F.prototype- 又因为
F.prototype = Base- 所以
b2.__proto__ = Base
- 从图中可知道,通过
Object.create构造的b2没有指向Base的prototype,而是直接执行Base【即:b2.__proto__ = Base而不是b2.__proto__ = Base.prototype】, 所以在Base.prototype上定义的b,只单纯是Base.prototype上的一个属性。
传递给Object.create()的参数是对象
const person = {
name: 'jm',
age: 12
}
const obj = Object.create(person)
console.log(obj)
- 结果如下图:

总结
new关键字必须是以function定义的。Object.create()则function和object都可以进行构建。