为什么说js没有继承

基于对象

描述

面向对象的三大特征继承,封装和多态,完全实现就是面向对象(Object-Oriented),没有完全实现就是基于对象(Object-Based)

度娘解释

基于对象的编程语言没有提供象抽象、继承、重载等有关面向对象语言的许多功能。而是把其它语言所创建的复杂对象统一起来,从而形成一个非常强大的对象系统,以供使用。

即阉割版面向对象,比如VB,JavaScript

区别

1.面向对象的技巧,尤其是设计模式,很多都不能直接使用,用了更蛋疼
2.很多时候js下描述的继承与java描述的继承不一样


基于原型的继承

软件 = 结构 + 算法 ,针对面向对象,这里的结构指是对象(什么是对象),继承用于描述两个对象(结构)的逻辑关系

面向对象继承的逻辑问题

而这个逻辑在具体描述时,又有各种逻辑细节
1.封装
比如可继承与不可继承(即封装性)
2.抽象
继承是结构,指的是逻辑关系,具体的业务并不重要
继承绝不会以来一个具体的对象,这是与js最大的区别
3.其他关键词
interface,abstract,override,overload,super...
均为对继承或者三大特性具体逻辑的处理,再具体一点就是jvm规范

js的继承的逻辑问题

js通过构造器,实现如何描述两个结构的关系,针对面向对象的逻辑问题,会进行选择性实现(无视),逻辑上只有两点
1.对象(实例)只有构造自某个原型
即实例不存在拥有原型的问题
而构造器有原型,指向的就是原型,这是基础逻辑观点

2.原型也(必须)是一种实例
对于基于类实现体系来讲,类是一个抽象,继承的也可以是抽象结构,甚至可能都不算一个结构对象
js继承必须是一个实例

js的继承的实现

没有固定语法,只有对原型对象的理解,提出的解决方案
所以有人说基于对象没有继承,第一原因就是没有语法

针对使用,处理掉js的继承的两项逻辑问题即可
第一种有结构器型

//1.原型是一种实例
Son.prototype = new Father();
// 2.构造器有原型,且指向原型
Son.prototype.constructor = Son;

第二种无结构器型

 function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
  }
  var b = obj({
    a:1
  })

这里最大的槽点在于,手动修改指向,以及没有完善的验证系统

js继承关系,更多的是规范一对多的引用关系

继承用于描述两个对象(结构)的逻辑关系,实现时,更多的是解决内存的复用,如果单说描述对象的关系,不用原型也可以实现,如

function Son{
  this.father = new Father();
}

或者使用内置的father属性(随便写的),并在构造器中,自行进行如上处理

Son.father = Father

又或者加上内存复用,进行如下复用

//对象定义
Father(){

}

Son(){
}

//父级实例的应用
var father = new Father();
//子实例的应哟
var son1 = new Son();
//手动创建关联
son1.father = father;
var son2 = new Son();
son2.father = father;

在这里描述原型链的作用,大致就是减少手动创建关联的次数,以及规范化

js的继承实现与java继承的逻辑区别

最后,js没有继承的一个原因是,手动出来实例对象,本身就是组合的一种方式,因为基于类的继承的父类实例是不能(很难)拿出来使用的,如果有反复使用的需求,组合就是替代方案
比如在java中

public class Father {
    static int count = 0;
    Father(){
        count++;
        System.out.println("父类实例初始化"+count);
    }
}   

public class Son extends Father {
    Son(){
        System.out.println("子类实例初始化");
    }
}

    
public static void main(String[] args) {
    Son son1 =  new Son();
    Son son2 =  new Son();
} 

运行结果是

父类实例初始化1
子类实例初始化
父类实例初始化2
子类实例初始化

继承的是抽象,逻辑和对象的关系,父类的构造器创建了两次,但父类的具体实例是不存在的,描述一下就是son1与son2都继承至父亲(父类),他们的父亲(父类)有通用的特点,但他们是谁,不知道

如果业务上一定要描述出父类,那一定会使用组合,实例化父类后,进行业务上的连接,无论是代理,装饰或者其他类似的模式,也使用相似的方式进行处理,依赖于手动创建父类

public class Son {
    Son(Father father){
       this.father = father;
    }
}

对应js继承实现的语义

//father 是一名父亲(父类的实例)
var father = new Father();
//他有很多儿子
Son.prototype = new Father();
Son.prototype.constructor = Son;
//大儿子
var son1 = new Son();
//小儿子
var son2 = new Son();

这就是为什么说
js没有继承,只有组合,原型链代码复用的意义大于描述对象结构关系

官方定义

ECMA-262-3

http://dmitrysoshnikov.com/ecmascript/chapter-7-1-oop-general-theory/

另一个原因是官方对继承的定义,ECMA-262-3,针对继承一块的描述

For improvement of a code reuse, classes can extend other classes, bringing necessary additions. This mechanism is called as (hierarchical) inheritance.

中文翻译

为了提高代码重用,类可以从一个扩展为另一个,在加上额外的信息。 这种机制被称为(分层)继承 。

这就是为什么我会说js的继承,强调的是复用,无论代码上还是内存上,而对其逻辑上的设计关系并没有描述
后续有描述到继承链,关于继承链,我带入的理解就是原型链

java规范有一节是对所有概念的定义,关于继承这一块的描述不同于js,很遗憾,没有找到

self

再然后就是js参考的语法基础,self,这里一直强调的是动态继承以及traits(类似于mixin)
这块文档基本都没了,只是凭映像描述

使用

最后是使用上,除了最开始写组件会很OO外,其他时候能用上,真的是看在组合的意义上,比如Vue,VueComponent继承Vue,假设他是基于类的描述,这里是不可能让VueComponent继承Vue的,只会组合,比如

function VueComponent(vue){
    this.vue = vue;
}

//使用
<script>
{
  methods;{
    back(){
        this.vue.$router.back(-1);
    }
  }
}
</script>

这是引擎和解析对象,工厂与产品的关系,逻辑上不可能继承出来的

使用场景

只要不是多对多的关系都可以实现js的继承,主要看是否需要,比如强行VueRouter继承Vue(当然,一对一的继承除了少些一个指向,整体意义不大,有点通过bind修改this的意思)
唯一的问题是改变原型需要获取到vue的实例,两种处理
1.代理/工厂,即由VueRouter提供Vue创建的功能
显然是越权了
2.主动提供vue的实例
那这个就是组合了

这也是为什么会说,不是自己写的,或者有框架级方案,不要主动去继承
没有框架级语法约束,继承的基类的升级,对被继承来讲很容易是毁灭级的(主要指属性或方法重名)

总结

js通过原型链实现的动态继承,主要目的是代码复用,而不是用OO的思想设计和编程,这是我个人经验的描述

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,701评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,649评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,037评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,994评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,018评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,796评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,481评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,370评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,868评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,014评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,153评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,832评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,494评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,039评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,437评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,131评论 2 356

推荐阅读更多精彩内容

  • 设计模式概述 在学习面向对象七大设计原则时需要注意以下几点:a) 高内聚、低耦合和单一职能的“冲突”实际上,这两者...
    彦帧阅读 3,749评论 0 14
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,106评论 1 32
  • 博客内容:什么是面向对象为什么要面向对象面向对象编程的特性和原则理解对象属性创建对象继承 什么是面向对象 面向对象...
    _Dot912阅读 1,424评论 3 12
  • 概要 64学时 3.5学分 章节安排 电子商务网站概况 HTML5+CSS3 JavaScript Node 电子...
    阿啊阿吖丁阅读 9,209评论 0 3
  • 关于战略的描述,马云主要提炼了6个关键词:使命、愿景、价值观、组织、人才、KPI。 其中,前三个决定了组织的方向,...
    Sting阅读 1,129评论 0 2