背景
我一直在使用C预处理器来管理和“编译”具有多个文件和构建目标的半大型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
和A
build
目录,并将.js文件放入
SRC
.
便利宏
最初,我只是想要预处理器的东西
包括:
也许还有几个
γIFIFF
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]);
}
前臂怎么样?
#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
(为了方便)和
这
(出于必要)。下面是一些示例代码:
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);
}
}
}
扩展呢?
所以这让我想到了一个问题…我们如何实现扩展作为一个宏来包装通常的“克隆原型,复制构造函数属性”JS原型继承?我没有找到一种方法可以做到这一点,除了要求扩展出现
之后
类的定义,这是愚蠢的。这个实验需要扩展,否则就没用了。只要其他宏给出相同的结果,就可以随意更改它们。
编辑-这些可能对扩展很有用;在这里列出它们是为了完整性。
#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(){}}())
提前感谢您的帮助、建议或热烈讨论。:)