继承、原型链、在组件开发上的应用

    大半年前写过关于原型链和继承的笔记了,不过今天看到一篇关于组件化开发页面的博客,14年的,那时候react、angular还没那么火吧,略有感触,还是写篇简单的读后感吧。

博客原文:【组件化开发】前端进阶篇之如何编写可维护可升级的代码

创建对象和对象继承:

    我一直觉得,前端js有两个地方是必须掌握的,一个是对象,一个是函数。其他相关概念,比如原型、继承、闭包等都是二者的延伸和应用罢了。虽然说函数也是对象,但它在javascript这门语言中和具体实践中已经远远超出对象的范畴,除了可以作为函数的输入和返回结果外,其可嵌套、可构成闭包形成隔绝作用域、可被调用(call、apply和IE9+支持的bind)等特性让我们可以轻易地构建灵活复杂的web应用。

    不过今天想讲的是js的继承。事实上“继承”这个概念,本来就是为了代码的复用和扩展。我们让新的对象能拥有(或说能使用)已有对象的属性or方法,这就是继承,当然,我们往往也会对新对象进行功能扩展。

    JS中的对象都有一个原型属性,指向另一个对象。这个对象中保存了一些属性和方法,以之为原型的实例都能共享到这些属性方法。A的原型是B,B也可以有个原型是C,A->B->C->...就构成了一个原型链。

    A能通过原型链获取到B、C中的属性方法。如果其中存在同名属性名,则调用时,原型链下游的属性会把上游的属性覆盖。B、C有同名方法,调用时只会调用B的方法。如果A已经有同名方法,则不会遍历原型链。

    这就是js中关于原型的基本常识。JS中的内置的对象如Array、Function等,其原型的原型也都指向Object.prototype。

    在日常,我们创建对象时,一般也就4种方式:

    1.直接创建字面量对象var o = {a:1};  此时o默认原型指向Object.prototype

    2.var o = Object.create(ProtoObj); 此时o的原型指向ProtoObj

    3.var o = new Foo();此时o.__proto__ 指向 Foo.prototype  (Foo构造函数的原型属性为prototype,但其实例的原型属性是__proto__)

    4.ES6的class定义类,并通过extends 继承父类.  但ES6的class只是语法糖而已。

初学者通过敲示例,或用简单的对象来做试验,很快就能弄清楚是怎么一回事。但在平时工作中,我们面对较多的还是写页面逻辑、绑定事件、样式切换、动画、后台交互数据等等,需要用的继承的地方并不多。就好像我们也很少在具体业务中用到Object.defineProperty()一样。

    但Vue框架背后的响应式原理,就是通过生成Vue实例时,对其data项的对象使用defineProperty()方法设置get/set函数,每当data中的数据被修改的时候观察者对视图进行刷新。

    有些只是在基础场景中体现不出价值,但在特定场景中善于利用往往可以成为利器。

    在MVVM框架出现以前,前辈们写组件、插件,往往遵循非常传统的方式,在一个文件的闭包中写一段功能代码,返回一个对象或函数。然后在其他页面中引入并调用这个接口。

    可是,如果应用中不同的地方都可以复用这个组件的抽象部分,我们就可以只创建一个基本版的组件。然后在需要的地方对它进行定向功能拓展就好了。

 1  var AbstractView = create({
 2    initialize: function (opts) {
 3      opts = opts || {};
 4      //...
 5    }
 6  });
 7 
 8 //特定组件
 9  var baseComponent = create(AbstractView, {
10     //...
11    }
12  });
13 //带特定行为的组件
14  var componentA = create(baseComponent, {
15      //渐进增强功能...
16    }
17  });
18 
19  var v1 = new baseComponent();
20  v1.show();
21  
22  var v2 = new componentA();
23  v2.show();

     然而,使用react的话,我们就不用这么麻烦走原声js的构建,因为每个class都是一个组件,通过HOC(高级组件)我们可以由一个基类扩展其功能生成另一个子类,实现按需增强。

原文地址:https://www.cnblogs.com/alan2kat/p/7858629.html