还在纠结 JavaScript 的继承?给你们看看什么是黑科技

2015-10-21 19:28:53 +08:00
 bramblex

猜猜下面的代码你们猜会是什么效果?

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);

BlxClass

GitHub

https://github.com/bramblex/BlxClass

简介

一个 JavaScript 面对对象的库,让你在 JavaScript 用上靠谱的面对对象特性。

使用

将本项目中的 dist/Class.js 复制到你的项目下

1. 在 nodejs 中使用

var Class = require('path/to/Class.js');
var ClassA = Class('ClassA', Object);

2. 在浏览器中使用

<script src="path/to/Class.js"></script>
<script>
    var ClassA = Class('ClassA', Object);
</script>

API

1. Class( class_name, parent_class)

Class 函数接受两个参数返回一个新类,第一个参数是新类的命名,第二个参数是继承自哪个类。如果并没有继承自别的类,那么直接写 Object 就好了。

var ClassA = Class('ClassA', Object);
var ClassB = Class('ClassB', ClassA);

2. name

类的名字

var ClassA = Class('ClassA', Object);
console.log(ClassA.name) // => ClassA
var ClassB = Class('some name', ClassA);
console.log(ClassB.name) // => some name

3. parent

类的父类

var ClassA = Class('ClassA', Object);
ClassA.parent === Object; // => true
var ClassB = Class('ClassB', ClassA);
ClassB.parent === ClassA; // => true

4. method( method_name, function )

定义方法,方法会被子类继承,并且能够重载。

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]

5. classmethod( method_name, function )

定义类方法,类方法不会被子类继承,也不能重载。

var ClassA = Class('ClassA', Object)
    .classmethod('run', function(){
        // 类方法
        console.log('class method run');
    });

ClassA.run(); // => class method run

6. extend( class_name )

继承出新类。

var ClassA = Class('ClassA', Object);

// 下面两种写法是等价的
var ClassB = Class('ClassB', ClassB);
var ClassB = ClassA.extend('ClassB');

7. alias( alias_name , method_name )

给方法取别名

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

8. uper( method_name )

调用父类方法

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
8115 次点击
所在节点    JavaScript
61 条回复
bramblex
2015-10-22 10:07:13 +08:00
@joyee

也是哈 /w\, 就是我比较喜欢造轮子
bramblex
2015-10-22 10:08:00 +08:00
@adspe

比如捏?什么意想不到的后果?
bramblex
2015-10-22 10:08:38 +08:00
@iwege

/w\ 好吧……
bramblex
2015-10-22 10:09:32 +08:00
@miro

面向对象语言我不用继承用什么?

难道有 typeclass 给我用嘛……
coolicer
2015-10-22 10:18:44 +08:00
好东西,但是很少用继承。
magicdawn
2015-10-22 11:36:05 +08:00
看了 xxxScript 源码, 炒鸡反感~没想到 LZ 还拿出说~
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()一类的诸多黑魔法实现…
bramblex
2015-10-22 13:01:43 +08:00
@wdhwg001

丑是丑,但是用起来还算顺手。如果要更简洁的语法的话,只能改语言语法本身了。
bramblex
2015-10-22 13:05:09 +08:00
@magicdawn

嗯,等你造一个更好用的我就用你的。 OwO
zythum
2015-10-22 13:05:54 +08:00
一般吧。这个多态判断不麻烦。
比较难的设计是访问权限 publish private, 和 优雅的 super 的设计 用 apply 的方式却是可用而且实用,但是太丑了了
bramblex
2015-10-22 13:08:40 +08:00
@zythum

其实重点不是难不难,判断麻不麻烦,而是好像没什么人想到……
zythum
2015-10-22 13:09:52 +08:00
@bramblex 什么没有人想到啊。老早就有了。只是你没有发现而已...
ggiiss
2015-10-22 13:30:36 +08:00
请参考 John Resig 大神 08 年的作品 http://ejohn.org/blog/simple-javascript-inheritance/
catface
2015-10-22 17:28:05 +08:00
项目描述是“ JavaScript 的面对对象库”
ianva
2015-10-22 17:53:23 +08:00
以前到热衷鼓捣这些东西, class 实现过这些,还有 mixin , attribute , aop 的功能,不过现在看来,除非整套体系都是自己造的,现在意义没这么大,这个时代已经不是基础工具造轮子的时代了,语言层面的标准化在是重要的,比如之前的 yui 3 的 base , widget 都很强大,但现在已经不维护了。
aivier
2015-10-22 17:59:37 +08:00
这么久了,我还是不知道“面相对象”是个什么。。。
Justineo
2015-10-22 18:24:37 +08:00
黑科技黑在哪里……实现了啥独有的功能?根据参数长度重载?随便 Google 一下 JavaScript overloading ,上来就有 John Resig 的这篇:

http://ejohn.org/blog/javascript-method-overloading/ 你自己看看时间吧……

再搜下会发现也有根据参数类型重载的。

还有你给的这些示例代码,命名一会儿全小写,一会儿下划线分隔,一会儿驼峰。还有调用父类方法的那个 `uper` 我猜是 `upper` 拼错了吧,但其实应该是 `super`。
bramblex
2015-10-22 18:40:00 +08:00
@Justineo

首先命名规范你喷个毛线?类 开头大写驼峰, 方法开头小写驼峰, 变量小写下划线这个有槽点我没看出来那里有槽点?

其次,我自己什么都没看就实现了跟 John Resig 一样的东西,那你的意思是不是我跟 John Resig 大神一个水平啊?那你有资格喷个毛?

我造一个玩具碍着你事了?无语
bramblex
2015-10-22 18:53:55 +08:00
@ggiiss

看这个大神的作品对我没有任何提高……
kokutou
2015-10-22 19:12:29 +08:00
@aivier 在 IDE 里面,万物皆可打点,然后出一大堆东西。。。

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

https://ex.noerr.eu.org/t/229960

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

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

© 2021 V2EX