2019年本命年已经够坎坷了,没想到2020开局更难,因疫情原因,公司公告说为了可持续发展,1月工资要等疫情稳定后在发放,当时心里就不平衡,本来打算再好好干半年,公司这边操作真是猝不及防,那好吧,第二天我直接提了离职继续在家躺尸,躺了20多天也累了,昨天回了长沙,准备好好复习一下基础知识,然后再是把驾照拿了,再去广州或深圳发展,不想再呆小公司了,太不靠谱了。
javascript中有很多种继承方式,比如组合继承,原型式继承,寄生式继承等,而寄生组合式继承结合了上面继承方式的优点,避免了其缺陷。寄生组合式继承的大致实现逻辑为通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。
代码截取自Vue-0.1的源码, 没想到吧!Vue的源码里面包含我今天要复习的知识点。
function ViewModel(){ // ..... } ViewModel.extend = extend function extend (options) { var ParentVM = this var ExtendedVM = function (opts, asParent) { if (!asParent) { opts = inheritOptions(opts, options, true) } ParentVM.call(this, opts, true) } // ExtendedVM.prototype继承ParentVM.prototype var proto = ExtendedVM.prototype = Object.create(ParentVM.prototype) // prototype的constructor指向构造函数 utils.defProtected(proto, 'constructor', ExtendedVM) return ExtendedVM } 复制代码
下面解释一下上面的代码:
Object.create(ParentVM.prototype)
,为创建的副本添加 constructor 属性,从而弥补因重写原型而失去的默认的 constructor 属性utils.defProtected(proto, 'constructor', ExtendedVM)
,将新创建的对象(即副本)赋值给子类型的原型。在ExtendedVM中调用父类的构造函数ParentVM.call(this, opts, true)
来继承不可共享的属性。
const ChildVue = ViewModel.extend({}) child = new ChildVue() // 这个里面调用ViewModel的构造函数 复制代码
这个例子的高效率体现在它只调用了一次 ViewModel构造函数,并且因此避免了在 ChildVue.prototype 上面创建不必要的、多余的属性。与此同时,原型链还保持不变。
写到这里差不多已经写完了,下次面试官问你寄生组合式继承可以直接搬Vue的源码跟他聊,这时他看到你还不差的回答,可能会问上面的代码中Object.create的内部是怎么实现的,别急,下面这段代码告诉你Object.create怎么实现:
var _create = function (o) { var F = function () {} F.prototype = o return new F() } // 或者也可以这样 _create = function (o){ var t = {} t.__proto__ = o return t } 复制代码
看到这,面试官可能会问__proto__
与prototype
的区别以及原型链相关的知识了,别担心, 我在掘金上看到了一篇讲原型链特别好的文章(不是我写的,他写的太好了,忍不住推荐),我现在推荐给你。
帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)
再推荐一篇相关的文章给你,也是关于javascript继承的,他们的文章都写的太好了