You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
constructor 方法是类的默认方法,通过 new 命令生成对象实例时,自动调用该方法。一个类必须有constructor 方法,如果没有显式定义,一个空的 constructor 方法会被默认添加。
Class 不能像构造函数那样直接调用,会抛出错误。
使用 extends 关键字实现继承,有一点需要特别说明:
子类必须在 constructor 中调用 super 方法,否则新建实例时会报错。如果没有子类没有定义 constructor 方法,那么这个方法会被默认添加。在子类的构造函数中,只有调用 super 之后,才能使用 this关键字,否则报错。这是因为子类实例的构建,基于父类实例,只有super方法才能调用父类实例。
不积跬步无以至千里。
关于【Step-By-Step】
本周是继承专题,在开始之前,需要先了解构造函数、原型和原型链的相关知识。
构造函数
构造函数和普通函数的区别仅在于调用它们的方式不同,任何函数,只要通过
new
操作符来调用,那它就可以作为构造函数;任何函数,如果不通过new
操作符来调用,那么它就是一个普通函数。实例拥有
constructor(构造函数)
属性,该属性返回创建实例对象的构造函数。有一点需要说明的是,除了基本数据类型的
constructor
外(null
和undefined
无constructor
属性),constructor
属性是可以被重写的。因此检测对象类型时,instanceof
操作符比contsrutor
更可靠一些。原型
我们创建的每个函数都有
prototype
属性,这个属性指向函数的原型对象。原型对象的用途是包含可以由特定类型的所有实例共享的属性和方法。在默认情况下,所有原型对象都会自动获得一个
constructor
属性,这个属性包含一个指向prototype
属性所在函数的指针。当调用构造函数创建一个新实例后,该实例的内部将包含一个指针,指向构造函数的原型对象(可以通过实例的
__proto__
来访问构造函数的原型对象)。实例.__proto__ === 构造函数.prototype
原型链
简单回顾一下构造函数、原型和实例的关系:
每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个可以执行原型对象的内部指针(可以通过
__proto
访问)。假如我们让原型对象等于另一个类型的实例,那么此时原型对象包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。加入另一个原型又是另一个类型的实例,那么上述关系仍然成立,如此层层递进,就构成了实例与原型的链条,这就是原型链的基本概念。
一图胜万言:
调用
instance.getType()
会调用以下的搜索步骤:instance
实例SimType.prototype
SubType.prototype
SuperType.prototype
,找到了getType
方法在找不到属性或方法的情况下,搜索过程总是要一环一环地前行到原型链的末端才会停下来。
所有引用类型都继承了
Object
,这个继承也是通过原型链实现的。如果在SuperType.prototype
还没有找到getType
,就会到Object.prototype
中找(图中少画了一环)。原型链继承
原型链继承的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
如
SubType.prototype = new SuperType()
;可以看出
colors
属性会被所有的实例共享(instance1、instance2、...)。借用构造函数
借用构造函数的技术,其基本思想为:
在子类型的构造函数中调用超类型构造函数。
组合继承
组合继承指的是将原型链和借用构造函数技术组合到一块,从而发挥二者之长的一种继承模式。基本思路:
使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承,既通过在原型上定义方法来实现了函数复用,又保证了每个实例都有自己的属性。
原型式继承
原型继承的基本思想:
借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。
在
object()
函数内部,先穿甲一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回了这个临时类型的一个新实例,从本质上讲,object()
对传入的对象执行了一次浅拷贝。ECMAScript5通过新增
Object.create()
方法规范了原型式继承。这个方法接收两个参数:一个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象(可以覆盖原型对象上的同名属性),在传入一个参数的情况下,Object.create()
和object()
方法的行为相同。在没有必要创建构造函数,仅让一个对象与另一个对象保持相似的情况下,原型式继承是可以胜任的。
同原型链实现继承一样,包含引用类型值的属性会被所有实例共享。
寄生式继承
寄生式继承是与原型式继承紧密相关的一种思路。寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数在内部已某种方式来增强对象,最后再像真地是它做了所有工作一样返回对象。
基于
person
返回了一个新对象 -——person2
,新对象不仅具有person
的所有属性和方法,而且还有自己的sayHi()
方法。在考虑对象而不是自定义类型和构造函数的情况下,寄生式继承也是一种有用的模式。寄生组合式继承
所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法,基本思路:
不必为了指定子类型的原型而调用超类型的构造函数,我们需要的仅是超类型原型的一个副本,本质上就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。寄生组合式继承的基本模式如下所示:
constructor
属性至此,我们就可以通过调用
inheritPrototype
来替换为子类型原型赋值的语句:只调用了一次超类构造函数,效率更高。避免在
SuberType.prototype
上面创建不必要的、多余的属性,与其同时,原型链还能保持不变。因此寄生组合继承是引用类型最理性的继承范式。
ES6 继承
Class
可以通过extends关键字实现继承,如:对于ES6的
class
需要做以下几点说明:constructor
方法是类的默认方法,通过new
命令生成对象实例时,自动调用该方法。一个类必须有constructor
方法,如果没有显式定义,一个空的constructor
方法会被默认添加。Class
不能像构造函数那样直接调用,会抛出错误。使用
extends
关键字实现继承,有一点需要特别说明:constructor
中调用super
方法,否则新建实例时会报错。如果没有子类没有定义constructor
方法,那么这个方法会被默认添加。在子类的构造函数中,只有调用super
之后,才能使用this
关键字,否则报错。这是因为子类实例的构建,基于父类实例,只有super方法才能调用父类实例。参考文章:
[1] 珠峰架构课(墙裂推荐)
[2] CSS-清除浮动
[3] 详解JS函数柯里化
[4] JavaScript数组去重
谢谢各位小伙伴愿意花费宝贵的时间阅读本文,如果本文给了您一点帮助或者是启发,请不要吝啬你的赞和Star,您的肯定是我前进的最大动力。 https://github.com/YvetteLau/Blog
The text was updated successfully, but these errors were encountered: