最近想整理一下 js 代码,想用 java 或者 C# 的思想去写,发现好麻烦啊,写一个基类都痛苦。
虽然 python 也是脚本语言,但它写起基类也没什么难度,接口形式的编程也很方便。
设计模式在 js 上很难套用。什么工厂模式、外观模式统统都写不了
比如,我想实现一个接口或者抽象基类,要求所有继承此类的子类都必须实现所有的方法。js 不知道怎么来写
1
mooncakejs 2017-09-12 10:33:51 +08:00
在 es 里接口声明比较麻烦,抽象基类还有办法,定义一个方法,实现直接 throw
|
2
mooncakejs 2017-09-12 10:34:08 +08:00
上 typescript,和 c# 基本差不了多少了。
|
3
thisisgpy 2017-09-12 10:34:08 +08:00 1
class gay {}
|
4
arzusyume 2017-09-12 10:34:53 +08:00
class Base {}
class A extends Base {} |
5
murmur 2017-09-12 10:35:18 +08:00 1
都上了 js 还在想设计模式 你中毒了。。js 要什么设计模式。。不都是推翻重来。。还要继承。。
|
6
SuperMild 2017-09-12 10:36:15 +08:00
js 本身不合适,如果不愿意享受原型链的乐趣,最好上 typescript
|
7
donlxn22 2017-09-12 10:36:57 +08:00
TypeScript
|
8
lamada 2017-09-12 10:37:46 +08:00
TypeScript 你值得拥有
|
9
xiaomeimei OP |
10
xiaomeimei OP @murmur 但有些基础的东西确实感觉可以用设计模式
|
11
murmur 2017-09-12 10:45:50 +08:00
@xiaomeimei 就算是 ES6/TS 背后还是丑陋的原型链
|
12
SuperMild 2017-09-12 10:48:10 +08:00
@xiaomeimei 不麻烦,比手写模拟真 OO 方便很多了。
|
13
xiaomeimei OP @murmur 是啊,背后相当丑陋。throw 的那种方法我想过了,但感觉好丑
|
14
murmur 2017-09-12 10:50:22 +08:00
|
15
xiaomeimei OP @SuperMild 又要我装一下编辑器了
|
16
zjsxwc 2017-09-12 10:51:08 +08:00
es5 基本不会去用继承(其实语法上也实现不了), 而是和 golang 一样通过组合来实现继承的作用, 比如我想要 obj2 拥有 obj1 的 methodB 能力, 可以这么写:
``` function Class1(constructParamA, constructParamB){ this.constructParamA = constructParamA; this.constructParamB = constructParamB; } Class1.prototype.methodA = function (){}; Class1.prototype.methodB = function (){ console.log(this.constructParamA+this.constructParamB); }; function Class2(constructParamA){ this.constructParamA = constructParamA; } Class2.prototype.methodB = function (){ this.constructParamA.methodB(); }; var obj1 = new Class1("foo","bar"); var obj2 = new Class2(obj1); obj2.methodB(); ``` |
17
mooncakejs 2017-09-12 10:51:45 +08:00
@xiaomeimei 配上 vscode 就不麻烦了。
|
18
xiaomeimei OP @murmur vue 已经在用了,用在网站上。而我们的浏览器扩展上用的是纯 js,直接换 vue,时间成本太高,划不来
|
19
xiaomeimei OP @zjsxwc 这种方式只可以实现子类使用了父类的 MethodB 方法,但不能强制子类也拥有 MethodA 方法
|
20
otakustay 2017-09-12 11:00:12 +08:00
|
21
Biwood 2017-09-12 11:06:59 +08:00
原型链继承怎么就不能用了?看了这么多层回复没一个像样的,根本不需要什么 ES6 语法,老老实实写代码会死么
|
22
mooncakejs 2017-09-12 11:12:54 +08:00
@Biwood 来个 abstruct method 或者 interface 看看
|
23
zjsxwc 2017-09-12 11:13:25 +08:00
@xiaomeimei #19 实现你这种需求的写法很多的,比如这么写:
``` function Class1(constructParamA, constructParamB){ this.constructParamA = constructParamA; this.constructParamB = constructParamB; } Class1.prototype.methodA = function (){ console.log("methodA >>"+this.constructParamA+this.constructParamB); }; Class1.prototype.methodB = function (){ console.log(this.constructParamA+this.constructParamB); }; function Class2(objOfClass1){ this.objOfClass1 = objOfClass1; for (prop in objOfClass1) { this[prop] = objOfClass1[prop]; //if ((typeof objOfClass1[prop]) == "function") { // this[prop] = objOfClass1[prop]; //} } } var obj1 = new Class1("foo","bar"); var obj2 = new Class2(obj1); obj2.methodA(); obj2.methodB(); ``` |
24
bramblex 2017-09-12 11:14:59 +08:00 2
在很多语言里面,基类就是破裤子上面的补丁,用来补泛型这个坑的,你现在拿着一条没有破洞的裤子问补丁在哪?你让我们怎么回答?
|
25
learnshare 2017-09-12 11:17:10 +08:00
TypeScript 认可度不低嘛
|
26
maomaomao001 2017-09-12 11:18:11 +08:00 via Android
原型链明明很好的呀,哪里丑陋了,不过这个时代,直接用 ts, es6.es7 不更好嘛
|
27
otakustay 2017-09-12 11:23:07 +08:00
另外几乎所有的设计模式都是面向接口来做的,基类?为什么一定要有基类?
|
28
murmur 2017-09-12 11:51:17 +08:00
@otakustay 打错了。。我以为新版改成 createReactComponent 了 我还没升级用的还是 15 的 es5 语法
至于你说原型链丑陋不丑陋 你和正统的 oo 比一下看父子那些关系不用 trick 能实现不就可以了 |
29
Tunar 2017-09-12 11:53:06 +08:00 via Android
js 怎样写一个鸡肋😂
|
30
wobuhuicode 2017-09-12 11:57:33 +08:00
JS 写继承:原型链继承 -> 构造函数继承 -> 组合继承 -> 寄生组合继承
|
31
MinonHeart 2017-09-12 11:58:22 +08:00
@Tunar 鸡肋😂
|
32
otakustay 2017-09-12 12:10:57 +08:00
@murmur 弱的是语言本身而不是原型链啊,class based OO 的所有功能在原型链上都可以做,trick 是语法层面上的工作,你不能怪罪于底下的概念对吧
|
33
murmur 2017-09-12 12:18:40 +08:00
@otakustay 我是有点不太喜欢语法糖的,浏览器里跑的不还都是 es5 语法么,super 字我记得是 es6 的糖
也不太相信 code map,我都升级到 chrome 60.0 了,动不动 code map 断点打不上,断点起飞,所以我宁可用 es5 语法,至少出错的时候停住的位置就是出错的位置 webpack1 打出来的东西还能停住断点,webpack2 的模块就全变成 eval("xxxxxxxxx")了,出错了断点都停不了。。 回楼上一些,不好意思扯远了,我是不太喜欢前端盲目继承的, 但是也不能说基类是泛型的坑,ts 是强类型,不喜欢基类 List<Object>你也可以,越强的约束管水平不好的越好,所以 java 能让一群水平一般的人堆起来做个大项目还能跑,在不考虑性能的前提下,当然对大牛无所谓 见过最恶心的继承就是 EasyUI,dialog->window->panel,但是实际上谁会用 window 和 panel ?我需要的是 dialog=panel+button+header,而不是 dialog extends window extends panel |
34
Hanggi 2017-09-12 12:27:31 +08:00
class Gay {
SorM() { } } |
36
murmur 2017-09-12 12:35:20 +08:00
@qiqico 可以让 hmr 的时候和 webpack1 一样展开全部代码不用 eval 那种么
sourcemap 是没问题 就是 50%的概率没用 不要说版本不一致我当然知道要刷新 现在是不打断点怎么让他停在可以看出是那句出错的地方 就是 pause on exceptions |
37
SilentDepth 2017-09-12 12:37:22 +08:00
拿 OOP 的经验生套到 JS 上,不觉得这样有多高效率,JS 本身也不是干这个的。如果实在要接口,写 TS 就好了,背后被转成了什么样何须操那么大的心。
@murmur #33 ES 版本更迭这事儿就扯远了,历史包袱是客观存在的,但咱还得向前看不是。至少箭头函数在 Chrome 里跑得飞起(尽管那不是一个语法糖)。Sourcemap 的问题,确实有断点打不准的情况,但通常不会差太多,不至于开发调试进行不下去(除非你一行代码套了 N 层 Lambda )。Webpack 2 出来的也是可以调的,我确信是你的配置有问题或你的代码风格需要适应一下。 最后说一句:Vue 大法好~ |
38
Mutoo 2017-09-12 12:50:12 +08:00
abstract 和 interface 是静态编译的语言在编译阶段的约束,作为脚本语言,只有在运行时才去处理这些东西没有什么意义。
|
39
X41822N 2017-09-12 13:03:14 +08:00
ts
|
40
wangyufeng 2017-09-12 13:14:27 +08:00
@SuperMild 乐趣?
|
41
SuperMild 2017-09-12 13:21:16 +08:00
@wangyufeng 哈哈哈,对,就是乐趣,对于很多情况来说,原型链已经够用,甚至比 OO 更简单、清晰。
|
42
mcfog 2017-09-12 13:42:36 +08:00
都是图灵完备的语言,只有 JS 上不需要用的设计模式,不存在 JS 上实现不了的设计模式
楼主需要抛开其他所有 OO 语言的经验来看 JS,市面上基于原型链的语言几乎只有 JS 这一家,而几乎没有设计模式或者讨论 OO 的文章会基于 JS 来聊,太多的关于 JS 的 OO 的文章也都是生搬硬套其他语言的做法来误人子弟 回到楼主的比如,比如别的语言里你可能写 interface MyInterface {methodA(); methodB();} class MyClass implements MyInterface {.....} ,实际上在表达的是“给我 methodA 和 methodB 这两个方法,我帮你对接剩余的逻辑”,那么换到 JS 里,直接把接口能力作为依赖就行了 class EsClass { constructor(methodA, methodB){} ... } |
43
sensui7 2017-09-12 14:31:56 +08:00
很讨厌楼主跟风用这个头像
|
44
qiuyk 2017-09-12 14:47:01 +08:00
|
45
xiaomeimei OP @mooncakejs 我试试吧。今天上午被禁了 1800s,回复太频繁了
|
46
xiaomeimei OP @otakustay 面向接口是对的
|
47
xiaomeimei OP @sensui7 哈哈~~~来咬我
|
48
xiaomeimei OP @mcfog 是啊,不能生搬硬套,要根据语言特点来写
|
49
sensui7 2017-09-12 16:22:49 +08:00
@xiaomeimei 深刻诠释了抄袭者的嘴脸, 我无所谓, 这本来就是恶搞的头像, 对比两个图片, 看细节
|
50
yunying 2017-09-12 17:10:05 +08:00
js 为啥不能用设计模式?我天天写代码都在用
|
51
otakustay 2017-09-12 17:29:02 +08:00
@murmur 你说的这些都很有道理,但是却和你的问题无关
原型链 - JavaScript/ES - JS 引擎,这是 3 个层面的东西,你说的所有问题,都存在于语言和引擎之上,因此去推导原型链本身丑陋是不合适的,JS 不是唯一的基于原型的语言,比如 LUA 就要好看不少,R 和 Perl 加上原型相关的包后也不丑 |
52
lizhenda 2017-09-12 18:29:10 +08:00
```javascript
// 刚好我之前项目想用写了个,供参考 ``` |
53
lizhenda 2017-09-12 18:30:22 +08:00
/**
* JavaScript Inheritance Class * * 实现了继承和定义对象,初始化自动调用 ctor() 构造函数,自带一个简单的 clone() 拷贝函数 * 每个 Class 都带有一个唯一 ID : _pid,每个 new 出来的对象也带一个唯一 ID : _uid (可以用于相同 Class 的不同对象) * * @author : zhenda.li */ /** * @name ClassManager */ var ClassManager = { pid: (0 | (Math.random() * 998)), // 每个 Class 的唯一 ID uid: (0 | (Math.random() * 998)), // 每个 New 出来的对象唯一 ID getPID: function () { return this.pid++; }, getUID: function () { return this.uid++; } }; (function () { var fnTest = /\b_super\b/; this.Class = function () { }; /** * Create a new Class that inherits from this Class * @static * @param {object} prop * @return {function} */ Class.extend = function (prop) { var _super = this.prototype; var prototype = Object.create(_super); var desc = {writable: true, enumerable: false, configurable: true}; function Class() { this._uid = ClassManager.getUID(); if (this.ctor) { this.ctor.apply(this, arguments); } } desc.value = ClassManager.getPID(); Object.defineProperty(prototype, '_pid', desc); for (var name in prop) { var isFunc = isFunction(prop[name]); var override = isFunction(_super[name]); var hasSuperCall = fnTest.test(prop[name]); if (isFunc && override && hasSuperCall) { desc.value = (function (name, fn) { return function () { var tmp = this._super; this._super = _super[name]; var ret = fn.apply(this, arguments); this._super = tmp; return ret; }; })(name, prop[name]); Object.defineProperty(prototype, name, desc); } else { prototype[name] = prop[name]; } } Class.prototype = prototype; desc.value = Class; Object.defineProperty(Class.prototype, 'constructor', desc); /** * 快捷设置属性方法 * e.g : obj.attr({ x : 1, y : 2 }); */ Class.prototype.attr = function (attrs) { for (var key in attrs) { if (!isUndefined(this[key])) this[key] = attrs[key]; } }; /** * 每个对象自带拷贝方法 * @return Class */ Class.prototype.clone = function () { var newObj = (this.constructor) ? new this.constructor : {}; for (var name in this) { var copy = this[name]; if ((typeof copy) === "Class") { newObj[name] = copy.clone(); } else { newObj[name] = copy; } } return newObj; }; Class.extend = arguments.callee; return Class; }; })(); |
54
lizhenda 2017-09-12 18:32:32 +08:00
评论不能写 MD 么,至于用法,
var Test = Class.extend({ /** * 构造函数, 初始化 */ ctor: function () { this.func(); }, func: function () { } }); |
55
lizhenda 2017-09-12 18:33:28 +08:00
当然,最好的办法是用 es6,直接上 class
|
56
azh7138m 2017-09-12 18:37:34 +08:00 via Android
工厂模式怎么就不能用了。。。。阿里云国际的控制台字段校验那个部分就是工厂模式啊
|
57
lijsh 2017-09-12 18:45:32 +08:00
|
58
littleshy 2017-09-12 18:51:46 +08:00
JS 是原型语言,不要用面向对象的思想去使用它。
|
59
chegde 2017-09-12 19:35:53 +08:00 via iPhone
TypeScript 大法好
|
60
aleung 2017-09-12 20:13:31 +08:00 via Android
不能说 js 不是 OO,js 是 prototype based OO
|
61
aleung 2017-09-12 20:18:23 +08:00 via Android
大家说面向对象的时候是不是只是在说 GOF 的设计模式呢?设计模式只是基于 OO 思想的一些使用场景,部分与语言特性相关。
|
62
exoticknight 2017-09-12 20:19:49 +08:00
请面向需求编程,不要为了编程而编程
|
63
springmarker 2017-09-12 20:27:36 +08:00
用 js 写一个 jvm,然后在上面开发
|
64
Pastsong 2017-09-12 20:33:41 +08:00
原型链是非常吊的设计,不要用 Java 和 C++ 的思想写 JS
|
65
libook 2017-09-13 01:00:17 +08:00
“想用 java 或者 C# 的思想去写 JS ”这注定会导致痛苦的体验。就像:
“想用开火车的思想去开轮船”、 “想用做馒头的思想做面包”…… 软件工程学中的面向对象编程思想是一种抽象思想,为了实现运用这种思想,Java 有 Java 的实现方式,C#有 C#的实现方式,JS 有 JS 的实现方式,为何不用 JS 自己的方式来实现这一思想呢? |
66
simo 2017-09-13 08:57:01 +08:00
理解设计思想,知道取舍;熟悉 js 语言特性,可自定义设计。
其实 js 越来越适合 c#/java 等开发人员转入了。 同时,js 语言特性的改变,逐渐的工程化,也增高入门门槛,可以筛掉很多前端混子 |
67
rwecho 2017-09-13 09:11:38 +08:00
传统设计模式针对的是面向对象编程语言
|