大家喜欢用 JavaScript 中哪一种继承方式?大家来说说自己的看法 OwO

2015-06-12 21:47:09 +08:00
 bramblex

JavaScript继承主要是两种形式:
1. 原型链继承
2. 拷贝继承

注:ES7标准中的class就暂时不考虑了,因为还没有具体去了解过,希望以后能完善到不需要自己实现那么那么蛋疼的东西了。

我个人倾向于原型链继承,因为原型链继承是JavaScript规范里面推荐的继承,并且最重要的是,可以用原生的 instanceof 判断类型!而拷贝继承不行!


因为以上的一些问题,所以我就自己做了一个简单的JavaScript面的对象库。大概有实现这么几个功能:
1. 封装好的构造函数不管写不写new操作符都不会产生错误了,当然我是倾向于不写new操作符。
2. 返回的构造函数是命名的,方便调试的时候追踪函数栈。
3. 封装了一个parent方法,可以方便访问父原型的构造函数或者父原型的方法。
4. 封装了一个alias方法,可以创建一个方法别名。

具体实现在具体实现在github上 >> 代码传送门

接下来来看一些简单的示例来看看怎么用。

// 首先定义一个Animal类(姑且称为类吧),继承自Objec,有一个构造函数。
var Animal = BlxClass.extend('Animal', Object, function(name, sound){
  this.name = name || null;  
  this.sound = sound || null;
});

Animal.prototype.call = function(){
  console.log(this.sound);
};

// 现在我希望定义一个doge类,继承自Animal。第一个参数 ‘Doge’ 是用来给构造函数命名的。
var Doge = BlxClass.extend('Doge', Animal, function(name){
  var sound = 'wang';
  BlxClass.parent(this, Doge, [name, sound]); // 调用父类的构造函数,因为初始化对象属性在父类构造函数里。
});

Doge.prototype.wang = BlxClass.alias('call');

// 现在实例化一个doge对象
var doge = Doge('Tom'); // 有没有 new 都没关系,结果相同。
doge.call(); // =>'wang'
doge.wang(); // =>'wang'

然后这样就跟其他语言类的继承大致相似了。然后大家更喜欢哪一种继承方式呢?都来说说自己看法吧。

4523 次点击
所在节点    JavaScript
54 条回复
yangmls
2015-06-12 23:41:23 +08:00
neoblackcap
2015-06-12 23:56:17 +08:00
是我的理解有问题吗?原型继承不就是指所有的新对象都是靠拷贝原型来的嘛?楼主你提这两个东西在底层真的有很大的区别吗?你确定不是跟class一样是个语法糖?
bramblex
2015-06-13 00:08:52 +08:00
@neoblackcap

这个不是你理解有问题,而是……你基本概念不清晰……
neoblackcap
2015-06-13 01:19:43 +08:00
@bramblex 若是可以的话,我想知道是如何划分这两种继承方式,因为我在网上也找不到“拷贝继承”这基本概念,翻GoF里面也没见过。看mdn都是说的是原型链继承
hbkdsm
2015-06-13 02:01:19 +08:00
@neoblackcap 我理解的 @bramblex 所谓的拷贝继承应该就是 mixin,不知道对不对。可问题是 ... mixin 根本就不是继承啊!
bramblex
2015-06-13 08:05:06 +08:00
@hbkdsm

https://zh.wikipedia.org/wiki/%E7%BB%A7%E6%89%BF_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6)

首先,拷贝继承是mixin没错了。但是你好像对继承的概念理解有些问题……
bramblex
2015-06-13 08:08:12 +08:00
@neoblackcap
@hbkdsm

不对,拷贝继承不是mixin……或者只能说有些时候mixin是拷贝继承的一个步骤而已……

http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance_continued.html
Zhang
2015-06-13 10:42:59 +08:00
没必要写javascript了,可以写其他语言再transcompile成javascript就行了。
bramblex
2015-06-13 10:50:13 +08:00
@Zhang 嗯,等我先把JavaScript折腾到极致了我再去转coffee,type之类的好了。不过我觉得应该折腾不到机制 OwO。因为折腾完了JavaScript语言本身,还有v8可以折腾
Zhang
2015-06-13 11:15:39 +08:00
@bramblex java、c/c++、php、objective-c、c#都可以翻译成javascript,没有必要折腾coffee,type之类的了。
Zhang
2015-06-13 11:21:38 +08:00
@bramblex 前几天发现几乎所有语言都可以transcompile成javascript,看来不知有多少人对javascript不满啊!
lrvy
2015-06-13 12:14:18 +08:00
@bramblex 莫与在人间 2333
neone
2015-06-13 12:16:32 +08:00
各有各的用处吧。
《Javascript高级程序设计 第三版》中 6.3.4 ‘原型式继承’ 一节中提到
“他(Douglas Crockford)的想法是借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型”,
“ECMAScript5通过新增Object.create()方法规范了原型式继承”。
所以我理解为如果想继承一个对象的同时又不想创建自定义类型的时候可以使用‘原型式继承’,其他的时候应该考虑‘寄生组合式继承’。
bramblex
2015-06-13 13:10:36 +08:00
@Zhang JavaScript有问题,但是不能否认JavaScript各种很好的特性。比如函数式的特性,比如闭包等等。

至于有那么多语言翻译成JavaScript,只能说明JavaScript火了。然后那些并不了解JavaScript又不想学习的人开始需要用自己熟悉的语言来实现JavaScript的项目了。

但是当然啦,JavaScript这货虽然有很多优秀的特性,但是坑也是一堆一堆的。说的难听点,JavaScript现在还根本就是断手断脚的残缺品嘛…… TnT
neoblackcap
2015-06-13 13:58:03 +08:00
@bramblex 我觉得你说的拷贝继承根本不能算是继承。所以才提出JS里面有继承也就是原型继承的论调。这个所谓的拷贝继承根本就是原型继承的那套思想,但是实现却用浅拷贝,我觉得只能算是一种实现方式,按道理实现原型拷贝要用深拷贝才对,浅拷贝的话,你修改子类对象一样会修改到父类对象,这样的效果就明显跟继承的初衷不符,跟OO思想不符。
jings
2015-06-13 14:29:13 +08:00
bramblex
2015-06-13 14:31:22 +08:00
@neoblackcap

没错,就是继承的实现方式…仅此而已…
magicdawn
2015-06-13 15:16:25 +08:00
原型呀。。。

之前面试,我直接甩了 util.inherits 源码 https://github.com/nodejs/io.js/blob/v2.3.0/lib/util.js#L714
sodatea
2015-06-13 15:25:04 +08:00
首先,class 是 ES6 标准不是 ES7
bramblex
2015-06-13 15:46:58 +08:00
@sodatea 手抖写错了,然后并不能改……

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/198118

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX