JavaScript 中的对象有一个特殊的 [[Prototype]]内置属性,其实就是对于其他对象的引用。
访问对象属性会先访问[[Get]],获取当前对象属性,如果不存在则会在[[Prototype]]原型链上面查找,
var anotherObject = {
a: 2
}
var myObject = Object.create(anotherObject)
for (var k in myObject) {
console.log('found:' + k) // a
}
('a' in myObject) // true
通过 Object.create
创建一样能关联 [[Prototype]]
对于对象的[[prototype]] 尽头是 Object.prototype
, 很多属性和方法都是 Object.prototype
上携带的。
var anotherObject = {
a: 2
}
var myObject = Object.create(anotherObject)
anotherObject.a // 2
myObject.a // 2
anotherObject.hasOwnProperty('a') // true
myObject.hasOwnProperty('a') // false
myObject.a++
anotherObject.a // 2
myObject.a // 3 myObject 自身创建了属性并,赋值添加
myObject.hasOwnProperty('a') // true
function Foo() {
// ...
}
var a = new Foo() // 在 new 后,会在对象 a 创建一个 [[Prototype]] 指向 Foo.prototype 所指的对象
Object.getPrototypeOf(a) === Foo.prototype // true
a
通过 new
创建后,会在 a
对象内的 [[Prototype]] 链接到 Foo.prototype
所指向的原型对象。
function Foo() {
// ...
}
Foo.prototype.constructor === Foo // true
var a = new Foo()
a.constructor === Foo // true 创建的对象也有 constructor 指向,构造函数
在 JavaScript 界里面,类名是需要大写开头的。
构造函数中原型对象中添加属性,会在实体对象中引用中出现。
function Foo(name) {
this.name = name
}
Foo.prototype.myName = function() {
return this.name
}
var a = new Foo('a')
var b = new Foo('b')
a.myName() // a
b.myName() // b
制造假的构造函数 constructor
function Foo() {}
Foo.prototype = {} // 新建一个空对象
Object.defineProperty(Foo.prototype, 'constructor', {
enumerable: false,
writable: true,
configurable: true,
value: Foo // 让 .constructor 指向 Foo
})
function Foo(name) {
this.name = name
}
Foo.prototype.myName = function() {
return this.name
}
function Bar(name, label) {
Foo.call(this, name)
this.label = label
}
Bar.prototype = Object.create(Foo.prototype)
Bar.prototype = Foo.prototype // 错误,这样会把 Bar 的原型对象关联到 Foo的原型对象
Bar.prototype = new Foo() // 错误,会有副作用
Bar.prototype.myLabel = function() {
return this.label
}
var a = new Bar('a', 'obj a')
a.myName() // 'a'
a.myLabel() // 'obj a'
function Foo() {
// ...
}
Foo.prototype.blah = ...
var a = new Foo()
a instanceof Foo // true
// 通过函数对象原型赋值跟着,构建新对象来判断是否当同继承链
Foo.prototype.isPrototypeOf(a) // true
Object.getPrototypeOf(a) === Foo.prototype // true
a.__proto__ === Foo.prototype // true (非标准浏览器的方法访问[[Prototype]])
// __proto__ 虚拟实现
Object.defineProperty(Object.prototype, '__proto__', {
get: function() {
return Object.getPrototypeOf(this)
},
set: function(o) {
Object.setPrototypeOf(this, o)
return o
}
})
instanceof 判断在 a 的整条[[Prototype]]链中是否指向 Foo.prototype
isPrototypeOf() 两个对象就能实现,b.isPrototypeOf(c)
判断 b 是否在 c 的原型连中
var foo = {
something: function() {
console.log('Tell me something good...')
}
}
var bar = Object.create(foo)
bar.something() // Tell me something good...
通过 Object.create
创建两个对象之间的关联
Object.create
的 polyfill
if (!Object.create) {
Object.create = function(o) {
function F(){}
F.prototype = o
return new F()
}
}