我一直使用C预处理程序来管理和“编译”与多个文件半大型的JavaScript项目和构建目标。这使得可以在JavaScript中完全访问C预处理器指令,如#include
,#define
,#ifdef
等。下面是一个示例构建脚本,所以你可以测试示例代码:
#!/bin/bash
export OPTS="-DDEBUG_MODE=1 -Isrc"
for FILE in `find src/ | egrep '\.js?$'`
do
echo "Processing $FILE"
cat $FILE \
| sed 's/^\s*\/\/#/#/' \
| cpp $OPTS \
| sed 's/^[#:<].*// ; /^$/d' \
> build/`basename $FILE`;
done
做一个src
和build
目录,并把.js文件中src
。
很方便的宏
本来我只是想预处理器时钟为#include
,也许几#ifdef
S,但我开始思考,是不是很高兴有一些很方便的宏太?随后进行了实验。
#define EACH(o,k) for (var k in o) if (o.hasOwnProperty(k))
酷,所以现在我可以写这样的事:
EACH (location, prop) {
console.log(prop + " : " location[prop]);
}
而且它将扩大到:
for (var prop in location) if (location.hasOwnProperty(prop)) {
console.log(prop + " : " location[prop]);
}
怎么样的foreach?
#define FOREACH(o,k,v) var k,v; for(k in o) if (v=o[k], o.hasOwnProperty(k))
// ...
FOREACH (location, prop, val) { console.log(prop + " : " + val) }
注意我们是如何潜入v=o[k]
的if
条件内,因此不会打扰应该遵循这个宏的调用花括号。
类样OOP
让我们先从一个命名空间宏观和一个不起眼但非常有用的js模式...
#define NAMESPACE(ns) var ns = this.ns = new function()
new function(){ ... }
做一些奇妙的东西。它调用一个匿名函数作为构造函数,所以它最后不需要额外的()
来调用它,而在它内部,this
引用由构造函数创建的对象,换句话说,就是名称空间本身。这也允许我们在命名空间中嵌套命名空间。
这里是我的全套类样OOP宏:
#define NAMESPACE(ns) var ns=this.ns=new function()
#define CLASS(c) var c=this;new function()
#define CTOR(c) (c=c.c=this.constructor=$$ctor).prototype=this;\
function $$ctor
#define PUBLIC(fn) this.fn=fn;function fn
#define PRIVATE(fn) function fn
#define STATIC(fn) $$ctor.fn=fn;function fn
正如你所看到的,这些宏在Variable Object
(为方便起见)定义很多事情都和this
(从必要性)。下面是一些示例代码:
NAMESPACE (Store) {
CLASS (Cashier) {
var nextId = 1000;
this.fullName = "floater";
CTOR (Cashier) (fullName) {
if (fullName) this.fullName = fullName;
this.id = ++nextId;
this.transactions = 0;
}
PUBLIC (sell) (item, customer) {
this.transactions += 1;
customer.inventory.push(item);
}
STATIC (hire) (count) {
var newCashiers = [];
for (var i=count; i--;) {
newCashiers.push(new Cashier());
}
return newCashiers;
}
}
CLASS (Customer) {
CTOR (Customer) (name) {
this.name = name;
this.inventory = [];
this.transactions = 0;
}
PUBLIC (buy) (item, cashier) {
cashier.sell(this, item);
}
}
}
约EXTENDS什么?
因此,这带来了我的问题...我们如何实现EXTENDS作为一个宏来包装通常的“克隆原型,复制构造函数属性”js原型继承?我还没有找到办法做到这一点之外,要求EXTENDS在之后出现这个类定义,这很愚蠢。这个实验需要EXTENDS或者没用。随意更改其他宏,只要他们给出相同的结果。
编辑 - 这些可能适用于EXTENDS;在这里列出他们的完整性。
#define EACH(o,k) for(var k in o)if(o.hasOwnProperty(k))
#define MERGE(d,s) EACH(s,$$i)d[$$i]=s[$$i]
#define CLONE(o) (function(){$$C.prototype=o;return new $$C;function $$C(){}}())
在此先感谢您的帮助,建议或热烈讨论。 :)
与GWT相比有哪些好处? – user123444555621 2010-07-27 09:15:37
那么,这仍然是JavaScript,只是扩展与宏。 GWT代码是用java编写的,'编译'为javascript。所以如果你熟悉javascript并且想要一种方便的方式来使用像命名空间这样类似熟悉的类设计,带有构造函数的类声明,继承等等......所有这些都可以在javascript中模拟,这些宏只是使它更方便。 – 2010-07-27 09:48:51