进阶高级前端系列——JavaScript的“类”、继承和委托

如果你想用JavaScript做一些高级的事情,例如打造组件库,封装插件,一定离不开“类”和继承,这是“封装”里无法绕过的一环。
为什么要给“类”加上引号呢?
因为JavaScript的世界里根本没有类,所有你见到的类,包括ES6里的新语法class,都不是真正的类,JavaScript是彻头彻尾的,纯粹到极致的面向对象语言,一切皆对象。
我劝你最好暂时忘了之前接触过的所有面向对象语言。因为他们可能早已深深地误导了你。
JavaScript的“类”和继承实际上是利用原型链来实现的。例如下面的代码:
在这里插入图片描述
这是js一个最常用的利用构造函数声明类的形式,里面有我们熟悉的new关键词,表面上看确实是先有了Foo类然后用new实例化了一个对象。
但实际上Foo只是一个函数,它和其它函数没有什么不同,函数也是对象,直接像普通函数一样直接调用Foo也不会出错,加上new之后只是多了几个操作:

  1. 创建一个新对象;
  2. 执行Foo函数,并将Foothis绑定到新对象;
  3. 把新对象的_proto_指向Fooprototype
  4. 如果Foo方法没有返回其它内容的话,返回这个新对象;
    这里我们看到a1并没有say()方法,但是a1.say()却正常运行了,这是原型链的作用,a1没有say属性,就去原型上查找,最终在Foo.prototype里找到。
    关于什么是原型链这里就不细说了,这属于js基础,不在高级讨论范围内。
    上面代码本质上我们是利用一个函数对象(Foo)又创建了另一个对象(a1),根本没有传统意义上的类!
    嗯?等一下!利用对象生成对象?这不应该是Object.create()该干的事儿吗?没错,上面的代码完全可以利用Object.create()重构!
    在这里插入图片描述
    这种写法更符合JavaScript一切皆对象的说法!而且更加清楚易懂,原型链从上到下清晰可见。
    JavaScript的new真是个千古大忽悠!还有更忽悠的,ES6里的class,让js的本质更加扑朔迷离:
    在这里插入图片描述
    多么美丽的代码,多么让人沉浸无法自拔,当当当!给我清醒点!千万别让它美丽的外表迷惑!它的本质跟第一段代码完全一样!语法糖而已,实际上这里并没有真正的类,class 仍然是通过 [[Prototype]]机制实现的。
    我们再来看看继承。
    因为JavaScript没有真正的类,所以所谓的继承也都是一些掩人耳目的做法,通过各种恶心的手段达到复用和重写的目的,来看看有多恶心:
    在这里插入图片描述
    代码里SubFoo继承了Foo,并且SubFoo重写了Foo的say方法,里面充满了大量的xxx.prototype,为了让SubFoo和Foo扯上关系,必须让它们的原型链链接起来:SubFoo.prototype = Object.create(Foo.prototype)。还有许多难以理解的借调(xxx.call()),特别是为了达到继承Foo的say方法而写的这一句:Foo.prototype.say.call(this),多么的丑陋。对于当初涉世未深的你能理解这几句代码里面的含义吗?为了理解这些你花了多久?
    为了我脑袋上所剩无几的头发,呸!
    当然有了ES6后情况有所好转:
    在这里插入图片描述
    还是那句话,语法糖而已,本质上还是要让Foo和SubFoo两个小东西互相扯来扯去,如果再深入一点——加上二级、三级继承——情况会无法想象地复杂。
    说到底这些其实都是强行使用类的思想来理解JavaScript的一切皆对象而出现的“变态”代码。如果你放下屠刀,换一个思路,使用JavaScript语言最初的设计思路就会发现,一切其实非常简单,我们用一切皆对象的思路再来实现一遍上面的逻辑:
    在这里插入图片描述
    怎么样?没有了乱七八糟的prototype和构造函数,不用担心原型链的走向,一切清新自然,而且最重要的,一切都是对象。
    这种实现方式的官方叫法(非人话叫法)就是“行为委托”。在行为委托模式中,Foo和 SubFoo只是对象,它们之间是兄弟关系,并不是父类和子类的关系。代码中 Foo委托了 SubFoo,反向委托也完全没问题,我们也不需要实例化类,因为它们根本就不是类,它们只是对象。此外,我们摆脱了一大堆的prototype和借调,我们使用了一种极其简单的方式完成了封装。
    当然往深处里讲,上述几种方式每个方式都有自己的优缺点。不能很武断地说这个好那个不好,在不同场景里选择最合适的实现方式是作为一名高级技术人员时刻该考虑的事情。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

毕竟我是大神

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值