var A = Class('A', Object)
.method('constructor', function(){
this.name = 'a';
});
var B = Class('B', A);
B.method('run', function(){
console.log('run');
});
var C = B.extend('C')
.method('run', function(a){
console.log('run a: ', a);
})
.method('run', function(a,b){
console.log('run a, b: ', a, b);
});
var c = C();
c.run();
c.run(1);
c.run(1,2);
https://github.com/bramblex/BlxClass
一个 JavaScript 面对对象的库,让你在 JavaScript 用上靠谱的面对对象特性。
将本项目中的 dist/Class.js
复制到你的项目下
var Class = require('path/to/Class.js');
var ClassA = Class('ClassA', Object);
<script src="path/to/Class.js"></script>
<script>
var ClassA = Class('ClassA', Object);
</script>
Class 函数接受两个参数返回一个新类,第一个参数是新类的命名,第二个参数是继承自哪个类。如果并没有继承自别的类,那么直接写 Object 就好了。
var ClassA = Class('ClassA', Object);
var ClassB = Class('ClassB', ClassA);
类的名字
var ClassA = Class('ClassA', Object);
console.log(ClassA.name) // => ClassA
var ClassB = Class('some name', ClassA);
console.log(ClassB.name) // => some name
类的父类
var ClassA = Class('ClassA', Object);
ClassA.parent === Object; // => true
var ClassB = Class('ClassB', ClassA);
ClassB.parent === ClassA; // => true
定义方法,方法会被子类继承,并且能够重载。
var ClassA = Class('ClassA', Object)
.method('constructor', function(){
// 构造函数
this.name = 'no name';
})
.method('constructor', function(name){
// 重载构造函数
this.name = name;
})
.method('run', function(){
// 普通方法
console.log('run');
})
.method('run', function(a,b){
// 重载上面定义的 run 方法
console.log('run a, b: ', a, b);
})
.method('run', '*', function(){
// 其他任意参数的情况
console.log(arguments);
});
var a = ClassA();
var b = ClassA('Li Lei');
console.log(a.name); // => no name
console.log(b.name); // => Li Lei
a.run(); // => run
a.run(1,2); // => run a, b: 1 2
a.run(4,5,6); // => [4,5,6]
a.run(7,8,9,0,1,2,3); // => [7,8,9,0,1,2,3]
定义类方法,类方法不会被子类继承,也不能重载。
var ClassA = Class('ClassA', Object)
.classmethod('run', function(){
// 类方法
console.log('class method run');
});
ClassA.run(); // => class method run
继承出新类。
var ClassA = Class('ClassA', Object);
// 下面两种写法是等价的
var ClassB = Class('ClassB', ClassB);
var ClassB = ClassA.extend('ClassB');
给方法取别名
var ClassA = Class('ClassA', Object)
.method('run', function(){
// 普通方法
console.log('run');
});
ClassA.alias('aliasRun', 'run');
var a = ClassA();
a.run(); // => run
a.aliasRun(); // => run
a.run === a.aliasRun; // => true
调用父类方法
var ClassA = Class('ClassA', Object)
.method('run', function(){
// 普通方法
console.log('ClassA run');
});
var ClassB = ClassA.extend('ClassB')
.method('run', function(){
ClassB.uper('run').apply(this, arguments);
console.log('ClassB run');
});
var ClassC = ClassB.extend('ClassC')
.method('run', function(){
ClassC.uper('run').apply(this, arguments);
console.log('ClassC run');
});
var c = ClassC();
a.run();
// => ClassA run
// => ClassB run
// => ClassC run
1
timeship 2015-10-21 19:35:06 +08:00
嘿嘿 在这也能碰见你
|
2
Gonster 2015-10-21 19:36:52 +08:00 via iPhone
啦啦啦, lz 又放黑魔法啦๛ก(ー̀ωー́ก)
|
5
lizhenda 2015-10-21 19:49:23 +08:00
很厉害的样子,确实不错。
|
6
qdwang 2015-10-21 19:49:39 +08:00 via Android
这科技 黑在哪里ǖ
|
7
domty 2015-10-21 19:53:31 +08:00
只看了第一个 demo
lz 是用 js 实现了单继承和方法重载? |
8
iwege 2015-10-21 19:56:46 +08:00
`(function(a,b){}).length`?
|
11
joyee 2015-10-21 20:02:53 +08:00
然而 ES6 已经有 class 和 extend 了……以及更加干净的新语法
|
12
icymorn 2015-10-21 20:10:31 +08:00
|
13
zrp1994 2015-10-21 20:11:01 +08:00 via iPhone
黑在哪里…
|
14
bramblex OP @joyee
1 ,没好看也没好用多少。 2 ,不能把类打开添加新方法。 3 ,不能重载。 4 ,没有配套的工具,比如最简单的,假设父类对我是一个黑箱,我需要调用父类的方法怎么办? 5 ,其实我的这个才更符合人们对基于类继承的面向对象的认知。 6 ,如果 JavaScript 要好好做成基于原型的面向对象语言,那么参考 Io lang ,我也没必要折腾这些了。 |
16
chendeshen 2015-10-21 20:18:45 +08:00
黑科技 @!!!
|
20
icymorn 2015-10-21 20:21:25 +08:00
@bramblex es6 可重载,而且对于我来说,看起来和其它语言里面的类声明更相近也更容易理解。
父类是个黑箱…… 这本来就是面向对象的思路吧,不关心黑箱,当然,要是有个逗逼写了个类太难用,只好 hack 回去就没法说了。 es6 目前支持度着急,浏览器上自己实现类的确按照你这样有很多便利。 |
21
haibocui 2015-10-21 20:21:40 +08:00
流弊
|
23
hronro 2015-10-21 20:23:36 +08:00
这个确实给力!
|
24
iwege 2015-10-21 21:40:09 +08:00 1
@bramblex
1 ,没好看也没好用多少。 从 stage 0 开始看起. import 反正我已经吐槽过了。但是 class 绝对是一个好帮手。 2 ,不能把类打开添加新方法。 prototype 还是可以访问的。也可以用子类的方式扩展。还有 es7 的 decorators 草稿标准。 3 ,不能重载。 可以 4 ,没有配套的工具,比如最简单的,假设父类对我是一个黑箱,我需要调用父类的方法怎么办? if(super.fn){super.fn()} 5 ,其实我的这个才更符合人们对基于类继承的面向对象的认知。 有争议 6 ,如果 JavaScript 要好好做成基于原型的面向对象语言,那么参考 Io lang ,我也没必要折腾这些了。 我觉得是一个方向性错误。 |
25
iwege 2015-10-21 21:43:03 +08:00
https://gist.github.com/iwege/d77cca95bb1d8c8a41f9
上面是用 stage 0 的标准模仿楼主写的简单的方法。逻辑上可能有副作用,只是证明可行性。 上面实际执行的结果如下: 1 print all {} print all { '0': 1, '1': 2, '2': 3 } [Function: fn2] fn2, print from base fn2 from Class A |
26
joyee 2015-10-21 22:31:30 +08:00
|
28
iamcho 2015-10-21 22:48:06 +08:00
mark
|
31
bramblex OP |
32
liangqing 2015-10-21 23:09:52 +08:00
提醒楼主,函数的 name 属性是个只读属性,所以设置也没用,有的浏览器还会抛异常。
|
35
iwege 2015-10-22 00:14:01 +08:00
@bramblex
这只是一个简单的 demo ,特性上我觉得没有什么,只是觉得语法上你的这种写法很啰嗦而已,部分实现的话新特性也可以支持,比如上面 fn 重复定义的问题,使用我的那个方法也可以简单的解决掉。上面的案例已经修改了。 https://gist.github.com/iwege/d77cca95bb1d8c8a41f9 同时尝试了自定义 class ,估计有点麻烦,但是也不是不可行。 overloadClass 可以支持拿到 class function 本身。 至于所谓的支持度,在有 transpiler 的情况下我向来不关心,我关心的是前端工程化,编码高效化以及问题定位速度。就像习惯了 coffee 或者 om 之后你让我再回去写 es5 的 js ,我是断然不乐意的。我的研究也只要能在 V8 里面跑就 OK 。 @icymorn 我也是第一次尝试用这个特性来做,因为工程化的话这种灵活性可能会是一种麻烦。当然既然用了 stage 0 干脆连`::`的写法也一起尝试用了。不过楼主的特性还不能完全支持,不知道混用两种方法能不能达到完全处理。 |
36
miro 2015-10-22 01:02:45 +08:00
少用继承...
|
37
HowardMei 2015-10-22 01:12:08 +08:00
好像很黑科技的样子,比 Typescript 的 Overload 强大,可人家是故意不让用 :)
|
38
fo2w 2015-10-22 01:52:23 +08:00
对于 lz 这种闲的蛋疼的人我只想说...
已粉... |
39
joyee 2015-10-22 02:04:49 +08:00 via Android 1
@bramblex 世界上只有两种语言,没人用的和被人骂的。。。论语言设计, 随便路边拦一个谁都能完爆 js ,又何苦拿它开刀。正是因为用的人太多,才不好丢掉历史包袱啊。
另外你用 transpiler 能有多少兼容性问题,转译出来的代码也就跟人手写这种类的差不多。。。 |
40
adspe 2015-10-22 09:37:03 +08:00
JavaScript 适用的场景用一般的几种模式的继承已经够了。如果放在一些 scale 比较大的场景会有很多意想不到的后果。
|
45
coolicer 2015-10-22 10:18:44 +08:00
好东西,但是很少用继承。
|
46
magicdawn 2015-10-22 11:36:05 +08:00
看了 xxxScript 源码, 炒鸡反感~没想到 LZ 还拿出说~
|
47
wdhwg001 2015-10-22 12:07:22 +08:00
还是觉得 Blackscript 法比较好,就是阮一峰提到的所谓 Minimalist Approach …
http://www.gabordemooij.com/blackscript 不得不说.method 有点太丑了。 脑补一个语法的话… https://gist.github.com/wdhwg001/9f83c9c21754d538886e 大致想了一下可以用 get:function()和 set:function()一类的诸多黑魔法实现… |
50
zythum 2015-10-22 13:05:54 +08:00
一般吧。这个多态判断不麻烦。
比较难的设计是访问权限 publish private, 和 优雅的 super 的设计 用 apply 的方式却是可用而且实用,但是太丑了了 |
53
ggiiss 2015-10-22 13:30:36 +08:00
请参考 John Resig 大神 08 年的作品 http://ejohn.org/blog/simple-javascript-inheritance/
|
54
catface 2015-10-22 17:28:05 +08:00
项目描述是“ JavaScript 的面对对象库”
|
55
ianva 2015-10-22 17:53:23 +08:00
以前到热衷鼓捣这些东西, class 实现过这些,还有 mixin , attribute , aop 的功能,不过现在看来,除非整套体系都是自己造的,现在意义没这么大,这个时代已经不是基础工具造轮子的时代了,语言层面的标准化在是重要的,比如之前的 yui 3 的 base , widget 都很强大,但现在已经不维护了。
|
56
aivier 2015-10-22 17:59:37 +08:00
这么久了,我还是不知道“面相对象”是个什么。。。
|
57
Justineo 2015-10-22 18:24:37 +08:00
黑科技黑在哪里……实现了啥独有的功能?根据参数长度重载?随便 Google 一下 JavaScript overloading ,上来就有 John Resig 的这篇:
http://ejohn.org/blog/javascript-method-overloading/ 你自己看看时间吧…… 再搜下会发现也有根据参数类型重载的。 还有你给的这些示例代码,命名一会儿全小写,一会儿下划线分隔,一会儿驼峰。还有调用父类方法的那个 `uper` 我猜是 `upper` 拼错了吧,但其实应该是 `super`。 |