区别
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
都可以进行构建。