例子:
function SuperType () {
this.property = true
}
SuperType.prototype.getSuperValue = function () {
return this.property
}
function SubType () {
this.subproperty = false
}
// 继承了 SuperType
SubType.prototype = new SuperType()
SubType.prototype.getSubValue = function () {
return this.subproperty
}
var instance = new SubType()
alert(instance.getSuperValue()) // true
可以通过两种方式来确定原型和实例之间的关系
instanceof
alert(instance instanceof Object) // true
alert(instance instanceof SuperType) // true
alert(instance instanceof SubType) // true
isPropertypeOf
isPropertyOf()
方法也会返回 truealert(Object.prototype.isPropertypeOf(instance)) // true
alert(SuperType.prototype.isPropertypeOf(instance)) // true
alert(SubType.prototype.isPropertypeOf(instance)) // true
在解决原型中包含引用类型值所带来问题的过程中,开发人员开始使用一种叫做借用构造函数(constructor stealing)的技术(有时候也叫做伪造对象或经典继承)。
function SuperType () {
this.colors = ['red', 'blue', 'green']
}
function SubType () {
// 继承了 SuperType
SuperType.call(this)
}
var instance = new SubType()
instance.colors.push('black')
alert(instance1.colors) // red, blue, green, black
var instance2 = new SubType()
alert(instance2.colors) // red, blue, green
function SuperType (name) {
this.name = name
}
function SubType () {
// 继承了 SuperType,同时海传递了参数
SuperType.call(this, 'Nicholas')
// 实例属性
this.age = 29
}
如果仅仅是借用构造函数,那么也将无法避免构造函数模式存在的问题——方法都在构造函数中定义,因此函数复用就无从谈起了。而且,在超类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。借用构造函数的技术也是很少单独使用的。
function SuperType (name) {
this.name = name
this.colors = ['red', 'blue', 'green']
}
SuperType.prototype.syaName = function () {
alert(this.name)
}
function SubType (name, age) {
// 继承属性
SuperType.call(this, name)
this.age = age
}
// 继承方法
SubType.prototype = new SuperType()
SubType.prototype.sayAge = function () {
alert(this.age)
}
var instance1 = new SubType('Nicholas', 29)
instance1.colors.push('black')
alert(instance1.colors) // "red, blue, green, black"
instance1.sayName() // "Nicholas"
instance1.sayAge() //29
var instance2 = new SubType('Greg', 27)
alert(instance2.colors) // "red, blue, green"
instance2.sayName() // "Greg"
instance2.sayAge() // 27
instanceof
和 isPrototypeOf()
也能够识别基于组合继承创建的对象function object (o) {
function F () {}
F.prototype = o
return new F()
}
object()
对传入其中的对象执行了一次潜复制例子:
var person = {
name: 'Nicholas',
friends: ['Shelby', 'Court', 'Van']
}
var anotherPerson = object(person)
anotherPerson.name = 'Greg'
anotherPerson.friends.push('Rob')
var yetAnotherPerson = object(person)
yetAnotherPerson.name = 'Linda'
yetAnotherPerson.friends.pushj('Barbie')
alert(person.friends) // "Shelby, Court, Van, Rob, Barbie"
object()
函数,然后再根据具体需求对得到的对象加以修改即可person
对象的两个副本Object.create()
与 object()
方法的行为相同Object.defineProperties()
方法的第二个参数格式相同:每个属性都是通过自己的描述符定义的。以这种方式指定的任何属性都会覆盖原型对象上的同名属性。例如“var person = {
name: 'Nicholas',
friends: ['Shelby', 'Court', 'Van']
}
var anotherPerson = Object.create(person, {
name: {
value: "Greg"
}
})
alert(anotherPerson.name) // "Greg"
function createAnother (original) {
var clone = object(original)
clone.sayHi = function () {
alert('hi')
}
return clone
}
var person = {
name: 'Nicholas',
friends: ['Shelby', 'Court', 'Van']
}
var anotherPerson = createAnother(person)
anotherPerson.sayHi()
person
返回了一个新对象——anotherPerson。新对象不仅具有 person
的所有属性和方法,而且还有自己的 sayHi()
方法object()
函数不是必需的,任何能够返回新对象的函数都适用于此模式function SuperType (name) {
this.name = name
this.colors = ["red", "blue", "green"]
}
SuperType.prototype.sayName = function () {
alert(this.name)
}
function SubType (name, age) {
SuperType.call(this, name) // 第二次调用 SuperType()
this.age = age
}
SubType.prototype = new SuperType() // 第一次调用 SuperType()
SubType.prototype.constructor = SubType
SubType.prototype.sayAge = function () {
alert(this.age)
}
var instance = new SubType('Nicholas', 29)
SubType
构造函数时,又会调用一次 SuperType
的构造函数,这一次又在新对象上创建了实例属性 name
和 colors
。于是,这两个属性就屏蔽了原型中的两个同名属性。function inheritPrototype (subType, superType) {
var prototype = object(superType.prototype) // 创建对象
prototype.constructor = subType // 增强对象
subType.prototype = prototype // 指定指定对象
}
inheritPrototype()
函数的语句,去替换前面例子中为子类型原型赋值的语句了function SuperType (name) {
this.name = name
this.colors = ['red', 'blue', 'green']
}
SuperType.prototype.sayName = function () {
alert(this.name)
}
function SubType (name, age) {
SuperType.call(this, name)
this.age = age
}
inheritPrototype(SubType, SuperType)
SubType.prototype.sayAge = function () {
alert(this.age)
}
SuperType
构造函数,并且因此避免了在 SubType.prototype
上面创建不必要的、多余的属性。于此同时,原型链还能保持不变;因此,还能够正常使用 instanceof
和 isPrototypeOf()
。