本文根据 JavaScript标准参考教程 整理笔记
构造函数
function Person(options) {
this.name = options.name
this.age = options.age
this.say = {
console.log('我是人类')
}
}
var person ={name: 'yong', age: 20}
var ps = new Person(person)
ps.name //yong
ps.age //20
通过构造函数我们可以生成新对象ps
, 通过新对象我们可以获取name
, age
属性. 但是缺点也是存在的:
var person1 ={name: 'yong', age: 20}
var person2 ={name: 'yong2', age: 21}
var ps1 = new Person(person1)
var ps2 = new Person(person2)
ps1.say === ps2.say //false
我们发现生成的新对象实例, 都有一个say函数, 如果我们想让两个新对象实例共享一个属性呢? 那就将想要共享的属性放在原型上.
原型
Person.prototype.say = function() {
console.log('我是人类')
}
ps1.say === ps2.say //true. 实例对象ps1,ps2通过原型链查找到say函数
如果在当前实例中没有我们想要的属性或者函数, 那么当前对象就会沿着原型链查找原型上是否有属性(函数). 若有则返回, 若没有则继续向上一层原型查找.
在用构造函数生成实例对象的同时, 会有两件事值得注意:
- 构造函数的
prototype
属性会指向原型 - 生成的实例对象有一个
__proto__
属性也会指向原型,__ptoto__
属性不是标准, 但是大多数浏览器都实现了这一属性. - 原型有一个
constructor
属性指向构造函数
Person.prototype === ps1.__proto__ //true
Person.prototype === ps2.__proto__ //true
Person.prototype.constructor === Person //true
原型链
看完上面的例子, 应该就有一下概念了.
所有对象那个都有原型, 那么每个对象不停的向上回溯, 都会上溯到原型Object.prototype
, 即Object
构造函数的prototype
属性.
而Object.prototype
的原型是null
Object.prototype.__proto__ === null
这也就能解释所有对象都有toStirng()
方法了.因为所有的对象都会向原型查找toString()
方法, 直到找到了或者没有找到为止.
某一原型的实例对象可以通过原型链获取原型上的属性或者函数, 就如上例一样:
ps1.say === ps2.say //true
ps1.say === Person.prototype.say //true
constructor属性
每个原型都有一个constructor
属性, 这个属性指向构造函数:
Person.prototype.constructor === Person //true
对于Person.prototype
生成的实例对象, 可以通过原型链取得constructor
属性:
ps1.__proto__.constructor === ps1.constructor //true
ps1.__proto__.constructor === Person //true
ps1.constructor === Person //true