Skip to content

Latest commit

 

History

History
188 lines (142 loc) · 3.82 KB

原型.md

File metadata and controls

188 lines (142 loc) · 3.82 KB

原型

[[Prototype]]

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()
  }
}