我是靠谱客的博主 独特蜜蜂,最近开发中收集的这篇文章主要介绍JS继承复习20190110,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部