バックグラウンド
私は C プリプロセッサを使用して、複数のファイルとビルド ターゲットを含むセミ大規模な JavaScript プロジェクトを管理および「コンパイル」しています。これにより、javascript 内から 、 、 など#include
の#define
Cプリプロセッサ ディレクティブに完全にアクセスできます。#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
秒間必要だったのですが、便利なマクロもいくつかあるといいのではないかと考えました。実験が続いた。
#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
NAMESPACE マクロと、あいまいだが便利な 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 をマクロとして実装して、通常の「プロトタイプのクローンを作成し、コンストラクターのプロパティをコピーする」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(){}}())
ヘルプ、アドバイス、または活発な議論をよろしくお願いします。:)