概述
1.原型链继承
function Parent() {
this.parentValue = 'parent'
}
Parent.prototype.go = function() {}
function Son() {
this.sonValue = 'son'
}
Son.prototype = new Parent()
Son.prototype.say = function(){}
var son = new Son()
console.log(son.parentValue) // 'parent'
console.log(son.constructor) // Parent
console.log(son instanceof Son) // true
console.log(son instanceof Parent) // true
console.log(Son.prototype.isPrototypeOf(son)) // true
console.log(Parent.prototype.isPrototypeOf(son)) // true
//总结: son实例指向Son的原型对象(原型为Parent的实例),Son的原型对象指向Parent的原型对象
// son.constructor为什么不等于Son:Son的原型对象被重写,指向了Parent的原型对象,而Parent.prototype.contructor=Parent。
// 【注】:再通过原型链实现继承时,书写原型属性不要通过对象字面量的方法,这样会重写原型 eg:xx.prototype = {xx:xx}
// 缺点:假如Parent构造函数中有引用类型值的属性会被共享
function Super() {
this.ary = [1,2,3]
}
Super.prototype.number = 2
function Sub() {
this.array = ['a', 'b']
}
Sub.prototype = new Super()
var sub1 = new Sub()
console.log(sub1.ary) // [1,2,3]
sub1.ary.push(4)
var sub2 = new Sub()
console.log(sub2.ary) // [1,2,3,4] ary的值被多个实例共享,其原因就是Sub的原型对象是Super的实例,其继承了Super构造函数里面的所有属性
2.借用构造函数继承
function Super2(name) {
this.ary = [1,2]
this.name = name
}
Super2.prototype.getAry = function() {
return this.ary
}
function Sub2(name) {
Super2.call(this, name) // 调用Super2构造函数实现继承
}
var sub2 = new Sub2('asd')
console.log(sub2, sub2.ary) // [1,2]
console.log(sub2.name) // asd
sub2.ary.push(3)
var sub3 = new Sub2('asdf')
console.log(sub3.ary) // [1,2] // 有效的规避了引用类型值的共享问题
// 缺点:Super2的原型对象上的属性无法得到继承, 总不能把函数都写到Super2的构造函数中吧,这样又会让函数无法得到复用
3.组合继承(融合原型链和借用构造函数继承)
function Person(name) {
this.name = name
this.type = ['man', 'woman']
}
Person.prototype.getName = function() {
return this.name
}
function Student(name, age) {
Person.call(this, name)
this.age = age
}
Student.prototype = new Person()
Student.prototype.getAge = function() {
return this.age
}
Student.prototype.constructor = Student // 将constructor属性重新指回Student
var student = new Student('zzz', 18)
console.log(student.type) // ['man', 'woman']
console.log(student.getName()) // zzz
console.log(student.getAge()) // 18
console.log(student instanceof Student) // true
console.log(student instanceof Person) // true
console.log(student.constructor) // Student
// 缺点在寄生组合式继承中会说
4.原型式继承
function creatObject(originObject) {
function F () {}
F.prototype = originObject
return new F()
}
var origin = {
name: 'asdf',
ary: [1,2,3,4]
}
var newObject = creatObject(origin)
console.log(newObject.ary) // [1,2,3,4]
newObject.ary.push(5)
var newObject2 = creatObject(origin)
console.log(newObject2.ary) // [1,2,3,4,5]
console.log(origin) // { name: 'asdf', ary: [1,2,3,4,5] }
// 其实就相当于Object.create()方法去复制对象
// 用途:主要用于一些简单的复制对象,想让两个对象保持相似性,但是也要注意其引用类型的值是共享的
5.寄生式继承
function createObject2(originObject) {
var o = Object.create(originObject)
o.say = function() {
return '123'
}
return o
}
var newObject2 = createObject2(origin)
console.log(newObject2.say()) // 123
// 和工厂模式创建对象类似,缺点就是函数得不到复用,效率低
6.寄生组合式继承(组合式继承和寄生式继承)
/**
* 组合式继承缺点:会调用两次被继承的构造函数
* 第一次:Student.prototype = new Person()
* 第二次:Person.call(this, name)
* 之所以Person的实例属性不被共享的原因就是第二次的调用将这些属性添加到Student的实例中,
* 也就屏蔽了第一次调用时,在Student原型上添加的那些属性,但是原型上Student的原型上依然存在这些属性
*/
function Bar(name) {
this.name = name
this.ary = [1,2]
}
Bar.prototype.go = function(){}
function Foo(name, age) {
Bar.call(this, name)
this.age = age
}
Foo.prototype = Object.create(Bar.prototype)
Foo.prototype.constructor = Foo
var foo = new Foo('haha', 26)
console.log(foo.ary) // [1,2]
foo.ary.push(3)
var foo2 = new Foo('haha', 26)
console.log(foo2.ary) // [1,2]
最后
以上就是独特蜜蜂为你收集整理的JS继承复习20190110的全部内容,希望文章能够帮你解决JS继承复习20190110所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复