文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注!
JavaScript 是一种弱类型的语言,且函数是一等公民,因此在代码的组织上非常灵活,有非常多的方法可以实现代码的复用。
“函数是一等公民”的意思,即函数和其他的类型一样,并没有什么特殊。因此在 JavaScript 中,函数可以和其他类型的数据一样,被当成值返回、被当成参数传递、被不同的变量赋值/引用等。
具体到代码复用方面,在 JavaScript 中被使用最广泛的就是类和 Mixin。
类,即 Class,在 Java 等语言中,类是最基本的概念,所有的代码都要基于类来编写。对类一个最直观的理解是“它是对象的蓝本,对象的形状由类的定义来决定”。因此,只要我们将需要复用的代码封装到类中,然后在不同的场合都使用这个类的实例,就可以在各种不同的场合来复用这些相同的代码。
如果我们希望复用一部分代码,但是又希望不同场合的对象形状是不同的,则可能需要使用类的继承:将需要复用的代码放到基类中,将不同的部分放入不同的子类中,然后不同场合视需要使用不同子类的实例,但这些实例仍然可以共享基类的方法和成员,从而实现代码复用。
class Animal{
constructor() {
this.head=1;
}
eat() {
}
}
class Cat extends Animal{
constructor() {
super();
this.legs=4;
}
makeSound() {
console.log('miao');
}
}
在这个例子中,我们定义了一个类Animal,它头(head)的数量为1,并且有eat()方法。接下来有一个Cat类继承自Animal类,它加上了自定义的成员legs和makeSound(),并且从基类Animal中继承了head和eat(),因此它既可以使用自定义的成员,也可以利用基类的成员,这便是继承复用代码的方式。
在 ES6 之前,JavaScript 中是没有正统的“类”的概念的,这也是 JavaScript 饱受误解的一个重要来源:习惯了使用“类”来组织代码的开发者来到了 JavaScript 的世界后,发现他们熟悉的概念和模式都不见了,因此觉得这门语言本身是有非常大的缺陷甚至是“玩具语言”。
但是因为 JavaScript 在设计之初有参考一些 Java 的概念,加上它非常灵活,懂这门语言的开发者仍然可以使用一些方法来模拟类,从而将经典的基于类的概念和模式引入 JavaScript 中。这些方法中使用最广泛的就是“构造函数”加“基于原型的继承”。
上面的例子用构造函数和基于原型的继承,写起来类似这样:
function Animal(){
this.head=1;
}
Animal.prototype.eat=function() {
};
function Cat(){
this.legs=4;
}
Cat.prototype=new Animal();
Cat.prototype.makeSound=function() {
console.log('miao');
};
ES6 正式为 JavaScript 加上了“类”的概念,但它在概念和性质上与基于原型的类模拟相差不多,在日常使用的场景下,基本上可以认为它们是相同的。
而有时候为了代码的灵活或者兼容,开发者仍然会使用 ES6 之前的类的写法,Vue 源代码中亦是如此。为了避免无谓的争论,后文中将不区分 ES6 的类和 ES5 基于原型的模拟类,而统称为“类”。
Mixin 在一些中文文档中也被称为“混入”或者“混元”,是另一种实现代码复用的方式。在具体的原理上,类主要通过“继承”来复用代码,而 Mixin 则主要是通过“组合”。
Mixin 的具体做法是:定义一些单独的方法,然后在某一些时机(例如初始化),动态地修改当前使用的对象,将这些方法挂载到对象上去,从而实现不同对象中都可以使用同一个方法。这种行为充分地复用了 JavaScript 语言的动态性,在运行时修改对象,从而改变对象的行为,实现代码复用。
例如在 Vue 的构造函数定义中,就使用了一系列的 mixin 来扩展 Vue 类型的方法,以initMixin()为例:
export function initMixin (Vue: Class<Component>) {
Vue.prototype._init=function (options?: Object) {
}
}
当initMixin()被调用时,就会在传入的Vue变量(Vue 构造函数)的原型上添加_init()方法。
Vue 中大量使用了类似上面示例的 Mixin,从而使得功能代码可以分散在不同的代码文件中,从而保持代码结构简单。
继承和 Mixin 都能很好地达到代码复用的目的,但它们也有各自的优缺点。
当继承使用过多时,容易出现一些问题,例如继承层数过多、大量覆盖父类实现等,使用不当时会导致代码难以维护。关于这一点,可以参考更多的资料,例如被广泛流传的“组合优于继承”的说法,在此不再赘述。
Mixin 也有一些缺点,例如代码组织过于灵活,很容易导致代码间的互相引用混乱,从而影响可维护性。
因此在实际使用中,选择使用继承还是使用 Mixin 来组织代码并不是一个有明确答案的问题,需要根据实际情况来进行取舍。Vue 中大量使用了 Mixin 来组织代码。
了解类和 Mixin 有助于我们从宏观上去构架代码,从而使文件组织更合理,代码结构更可读。而具体到 Vue 源码上,则能帮助我们拨开 Vue 源码结构上的迷雾,使我们在阅读 Vue 源码时不被与类和 Mixin 有关的代码干扰,从而更好地理解 Vue 的代码组织形式和各个部分的实现原理。
欢迎关注「慕课网」,发现更多IT圈优质内容,分享干货知识,帮助你成为更好的程序员!
日,位于北京海淀区四季青镇的Wehouse小区业主沈强(化名)向新京报记者反映,“我们小区别墅区里的旧违建没有完全拆除,近期还增添了一些新违建。我们被违建问题困扰多年,一直得不到解决。”
对此,四季青城管队一位负责人回应记者说,“Wehouse小区的别墅区共有100多栋楼,每栋楼大概3户,加起来共有300多户,其中约有95%的住户存在不同程度的违建问题。目前,涉及违建的相关问题还在处理当中。”
违法住户钻空子,仍在建设新违建
今年9月29日,北京市人民政府第86次常务会议审议通过修订后的《北京市禁止违法建设若干规定》(以下简称“295号令”),于11月15日起正式施行。随着295号令的正式实施,推动了北京市违法建设执法体制更加优化,执法行为更加依法规范,助力实现违法建设新增“零增长”目标。
“但是近期,我们小区增添了新违建,急需治理。” Wehouse小区业主沈强对新京报记者说,“有些住户正在建设违建,城管部门来了就停工,城管部门走了就继续建。”
12月8日,新京报记者赶到了位于海淀区常青园路与通汇路交会处的Wehouse小区进行实地走访。当天,新京报记者从小区北门进入,看到一辆吊车正在施工作业,周围并无明显防护设施。
2020年12月8日,在Wehouse小区里,一住户家正在施工。
新京报记者注意到,这辆吊车正在对小区46号楼附近的房屋进行施工,附近多栋建筑已被黑色网格物围住,透过这些围挡可以看到内部有工人正在施工,不时还有工人将围挡外的沙石材料运进围挡内。当记者询问现场多位工人正在进行何种施工时,得到工人们的回应皆为“不清楚”或“不知道”。
那么,Wehouse小区这些正在施工的楼栋是否具备合法施工手续?新京报记者就此问题向小区属地的海淀区四季青镇政府及四季青城管部门进行反映,随后,几名城管工作人员来到现场,叫停了上述正在施工的工程。
“这些建筑确实是存在违法建设的情况。我们之前叫停过,也让这些住户及时拆除,其他相关问题还在处理当中。”四季青城管队赵姓负责人如是说。
10多年旧违建被“翻新”,变成5层“月子中心”
同日,新京报记者在Wehouse小区走访发现,小区里的居民建筑基本都是别墅样式,大部分居民建筑都已经经过了改建或者加盖。有些居民家将类似阳台的部位加盖了一层或一部分;有些居民家加盖了约两层的建筑;有些居民在门前的空地上从下往上建起了与原有住宅混为一体的楼体。
“除了新增违建以外,Wehouse小区里还有旧违建尚未拆除。我们被违建问题困扰多年,一直得不到解决。” 沈强如是说。
实际上,早在2019年5月13日,北京市规划和自然资源委员会、北京市城管综合行政执法局联合发布《关于立即处置在施违法建设的实施意见(试行)》,贯彻市委市政府对违法建设“零容忍”、实现动态“零增长”的重要举措。
2019年5月21日,有多位Wehouse小区业主曾向新京报记者反映,该小区里的违建难以拆除。2019年5月23日下午,新京报记者曾在Wehouse小区看到,小区4-1、4-2别墅在围挡内被紧锣密鼓地改造,地下部分区域已经被挖开,仅有几根柱子支撑着地上建筑。(详见https://www.bjnews.com.cn/detail/155870462214221.html)
彼时,四季青镇政府办公室工作人员向新京报记者表示,“2018年12月,四季青镇执法队对Wehouse小区巡查发现该处存在新生违建行为,执法队对该处新生违建责令停工,暂扣电镐等施工工具。截至2019年5月23日,执法队张贴约谈通知书和整改通知书10余次,暂扣电镐、发电机、冲击钻等施工工具30余件。”
然而,时至今日,4号楼的违建问题仍没有得到完全解决。小区业主朱晨(化名)介绍说,“去年,已经有居民向相关部门举报4号楼的违建问题,曾经受到多方关注。可是,现在4号楼的违建没有被拆除干净,4号楼经过‘加盖翻新’,变成了地上5层的宏伟建筑,地下部分也被进行了较大规模的改造,现在已经开起了‘月子中心’。”
2019年5月,Wehouse小区4号楼正在施工。
Wehouse小区4号楼经过加盖翻新,变成了地上5层的建筑。
本周,新京报记者在Wehouse小区4号楼附近探访时发现,与2019年5月相比,4号楼发生了很大改变,这栋灰白色的多层建筑无论从占地规模、高度还是整体风格气势已经明显超过小区其他居民家房子。从4号楼一层地面往上数,有5层窗户,类似一栋5层独栋建筑,现在已经基本装修完毕,透过玻璃门,可以看到内部的电子屏显示的字样为“月子中心”,并已经有工作人员在办公。
对此,四季青城管队赵姓负责人称,“Wehouse小区4号楼的违建基本都是十多年前建的,去年拆过一部分,目前还有一部分在处理阶段。”
对于Wehouse小区形成如此大面积的违建,小区多位居民认为小区物业公司负有一定责任。“如此大面积的违法建设,肯定有一些大型机械和大型车辆参与施工,施工人员的进出、施工材料的输入、建筑垃圾的运出等都不可能悄悄完成。”小区居民朱晨告诉新京报记者,小区居民进行装修等活动都需要向物业公司报备,加盖违建也绝非一朝一夕就能完成,物业公司不可能不知情,所以,物业公司没有尽到及时制止和上报的职责。此外,物业公司也未能对加盖违建的车辆和人员进行限制。”
针对居民所述物业公司问题,新京报记者多次与小区物业服务商北京博安物业服务有限公司联系,该公司张姓负责人表示,“我们就此问题向有关部门举报过、也制止过。”当记者问及相关施工车辆如何进入小区时,这名张姓负责人表示,“我们公司有人专门对接,我不能回答。”
对于物业公司的此种说法,多名业主表示:“Wehouse小区违建问题已经持续存在了很多年,业主的背景也不尽相同,单靠物业公司治理起到的作用很有限,主要还要靠政府相关部门协同下大力度,方能有效治理。”
政府部门:不是不想拆,是有难度
对于Wehouse小区违建问题的处理进展,新京报记者多次与四季青城管队进行联系。四季青城管队相关负责人回复记者时表示,“Wehouse小区住户地上楼层的规划基本都是2层到3.5层,超过的层数基本都是违法建筑。我们没有个别业主所说的选择性执法。由于管理的区域比较大,且Wehouse小区违建面积又比较大,涉及将近300户,处理起来有些难度,需要一步一步去处理。目前,我们已经将部分涉及违建的房子产权冻结,接下来能做到的只能是发现违建行为及时叫停,等待上级领导的下一步安排。”
对于Wehouse小区4号楼的违建问题,上述四季青城管队相关负责人称,“按照正规规划,4号楼前面是2层、局部是3层。大概从2006年开始,4号楼的违建开始施工,当年基本建成,但是没有装修。其间,城管队对4号楼进行过治理,拆过一部分,但直至现在,4号楼的违建问题尚未彻底处理,仍有相关问题在处理当中。”
随后,新京报记者就此事又联系到了海淀区四季青镇人民政府。一位程姓副镇长回复记者称,“关于个别业主所说的城管涉嫌‘选择性执法’问题,我将会去核查。关于违建问题的处理,我们将在依法依规的基础上发现一起处理一起,已经形成的违建,也要由城管队去依法依规处理,今后绝对不能允许违建新增。”
当地一位政府内部人士向记者透露,“目前,相关部门不是不想拆此违建,而是拆起来有难度,背后牵扯的人员众多,仅靠一个城管队太难了,要多部门协作起来才能真正治理好这些违建。” 近一年来,随着北京城市疏解工作的推进和继续提升城市环境的需要,相关部门加大对违建的拆除力度,势在必行。新京报记者将继续跟踪报道此事。
新京报记者 张建 摄影 张建
编辑 武新 校对 刘越
邮箱zhangjian@bjnews.com.cn
来源:新京报
已知如下数组: var arr=[ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]; 编写一个程序将数组扁平化去并除其中重复部分数据,最终得到一个升序且不重复的数组
组实例的 flat(),flatMap()
数组的成员有时还是数组,Array.prototype.flat()用于将嵌套的数组“拉平”,变成一维的数组。该方法返回一个新数组,对原数据没有影响。
上面代码中,原数组的成员里面有一个数组,flat()方法将子数组的成员取出来,添加在原来的位置。
flat()默认只会“拉平”一层,如果想要“拉平”多层的嵌套数组,可以将flat()方法的参数写成一个整数,表示想要拉平的层数,默认为1。
上面代码中,flat()的参数为2,表示要“拉平”两层的嵌套数组。
如果不管有多少层嵌套,都要转成一维数组,可以用Infinity关键字作为参数。
如果原数组有空位,flat()方法会跳过空位
flatMap()方法对原数组的每个成员执行一个函数(相当于执行Array.prototype.map()),然后对返回值组成的数组执行flat()方法。该方法返回一个新数组,不改变原数组。
flatMap()方法的参数是一个遍历函数,该函数可以接受三个参数,分别是当前数组成员、当前数组成员的位置(从零开始)、原数组。
然后,我们来看看文章开始的那道题目如何优雅的求解
如果你还有好的方法,欢迎在下面留言,我会补充上去,供大家学习参考
参考文章:
https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/8
*请认真填写需求信息,我们会在24小时内与您取得联系。