DTPab

印刷やデザイン、アドビ製アプリやスクリプトなど、雑多な技術ブログ

#includeにもスコープが適用される

大した話じゃないのですが、スコープ内で#includeして外部スクリプトを読み込む場合、当然スコープが適用され、スコープの外からは参照できなくなります。
一方、prototype拡張はこれまた当然ながらスコープなど関係なく拡張できます。

このことを利用すると、prototype拡張するコードをスコープ内で#includeすれば、変数などを余計に汚染させずにprototype拡張だけ行うことができます。

試しになんでもいいのでprototype拡張してみます*1

String.prototype.hoge = function (str){
    var result = this + str;
    return result;
    }

Stringオブジェクトに引数を設定してhogeメソッドを実行すると、その文字列が元のStringオブジェクトの末尾に追加されるという、とっても簡単なものを用意しました。実際には、もうすこしちゃんとしたエラー回避処理などを挟んだほうがいいですが、今回はこれで良しとします。
では、これをスコープの中で宣言してみます。

!function (){
    String.prototype.hoge = function (str){
        var result = this + str;
        return result;
        }
    }();

この関数の外で、例えば

alert("hogeeeeee".hoge("fuga"));

と実行しても、ちゃんとhogeeeeeefugaが返ってきます。prototype拡張しているので、当然ながらスコープの外からこのメソッドが使えます。
スコープがイマイチ飲み込めないひとは、同じように

$.writeln(result);

と関数の外で実行してみてください。スコープの外からは変数resultにアクセスできないのでエラーになります。
スコープ内で#includeした場合もこれと同じです。

以下のようなコードをjsxincファイルで保存します*2。中身は先ほどのStringオブジェクトのprototype拡張を行っているコードです。

var piyo = "この変数にはスコープ外からアクセス不可";
String.prototype.hoge = function (str){
    var result = this + str;
    return result;
    }

このファイルを、別のスクリプトからスコープ内で#includeします。

!function (){
    #include ~/desktop/fuga.jsxinc
    }();

$.writeln("プロトタイプ拡張成功?".hoge(" OK!")); //プロトタイプ拡張成功? OK!

という形で、無事prototype拡張されていることが分かります。
また、先ほどと同じように、スコープ内の変数にはアクセスできません。

$.writeln(piyo);

これはエラーになります。さっきと全く同じですね。

以上より、

  • #includeしたスクリプトで定義した変数などは、宣言したときのスコープに置かれる
  • prototype拡張はもともとのオブジェクトを拡張しているのでスコープは関係ない

ということになります。
特にスコープ内でスクリプト#includeする場合は注意してください。

動作確認上の注意として、ExtendScriptToolkit上での検証の場合、変数や拡張されたオブジェクトがスクリプト実行後も保存されてしまいます。何度も試す場合(特に手打ちで検証する際)は、ほかのアプリケーションを指定して試すか、ESTKを再起動してからやり直してみてください。

*1:スコープ、prototype拡張がなんのこっちゃ?という方は、JavaScriptの仕様について情報を仕入れてみてください。スクリプトを作るのに必須の知識ではないですが、知っておくとコーディングの幅が広がります。スコープについては関数について、prototype拡張についてはプロトタイプチェーンなどについてもあわせてどうぞ。

*2:わかりやすくするためにjsxincファイルとしましたが、実際にはjsxだろうがjsだろうが構いません。