【追記 19/4/22 15:08】
それでもやっぱりまだうまく行ってなかったようなので、他所からお借りしました。
【追記 5/30 13:06】
コードに不具合があったため修正しました。あるふぁ(仮)さん、いつもありがとうございます(記事末尾にも追記あり)。
【追記 5/30 15:30】
コードに不具合があったため修正しました。またまたあるふぁ(仮)さん、そして(-z)さん、ありがとうございます(コードをgistにアップしました)。
はじめに
先日、Array.filterをECMAScript3準拠のExtendScriptでも使いたいと思い、MDNのサイトからPolyfillを参照しました。
ところが、実際に動かしてみるとwhile文が無限ループする。
そもそもコードがほかのMDNのPolyfillと比べてとても汚い。汚いというか{}
が使われてないから非常に違和感がある。if文でthisArg
を調べて分岐させて似たようなwhile文を2つ書くというのも筋が悪い。なんだこのコードは。
というわけで書き直しました。ExtendScriptでもArray.filterを使いたいという方は、末尾のコードをどうぞ。
ECMAScript 5.1を参照
まずは公式ドキュメント(英文)を参照しました。
ECMAScript Language Specification - ECMA-262 Edition 5.1
原文と合わせて、@MD5500さんからお借りしているこちらを参照しました(多謝!)。
Array.filterメソッド
コードはgistにアップしました。
ちょっと冗長なコードですが、ECMAScriptに沿って定義したつもりです。間違いがあればご指摘いただけると助かります。
コードはこちらから拝借しています。
ExtendScriptでの使い方
Array
オブジェクトをプロトタイプ拡張するものです。一度定義したエンジン内*1では、どこでもArray.filter
メソッドが使えるようになります。
上のコードをそのままスクリプトの冒頭に記述してもいいですが、こういうものは#include
しましょう。
まずはコードを適当な名前で「array_filter.jsxinc」などとして保存します。#include
が前提のスクリプトは、拡張子をjsxincとします*2。
続いて、読み込みたいスクリプトの冒頭で#include array_filter.jsxinc
とします。これはスクリプトとこのjsxincファイルが同じフォルダ階層にある場合です。でなければ#include
のあとに絶対パスを記述するか、もしくは#includepath
で読み込み先のパスを定義して#include array_filter.jsxinc
とします*3。#includepath
は複数の参照先パスを定義できるので、覚えておくとExtendScriptでもライブラリ(のような感じで使うjsxincファイル)を扱いやすくなります。
コードの例
#include array_filter.jsxinc var a = [13,6,20,1].filter(function (ele, index, array){ return ele > 10; }); $.writeln(e); //13, 20
あくまで例なのでリテラルで定義した配列[13,6,20,1]
に直接filter
メソッドを呼びましたが、配列を変数に代入し、その変数に対して呼ぶ形でももちろん大丈夫です。
Array.filter
メソッドには3つの引数を持つコールバック関数を渡します(第二引数、第三引数は省略可能)。
コールバック関数の第一引数は配列から順に抽出した値です。
第二引数はそのindex(順番)、第三引数は配列それ自体です。
また、省略可能ですが、コールバック関数にthis
として渡したいオブジェクトも(Array.filter
メソッドの第二引数として)渡すことができます。このあたりはクロージャなどの入れ子の関数がたくさん存在するケースで威力を発揮しますが、ExtendScriptのちょっとしたスクリプトではまず使うことはないでしょうね。なので説明は割愛します。
コールバック関数は直接引数に記述しましたが、これも事前に定義しておいたものを変数として渡したり、といった形でも大丈夫です。
【追記 5/30 13:06】更新履歴
コールバック関数にreturn true
だけ、要するに全部trueで返す場合、元の配列と同じ配列ができるようにしました。
以前のコードでは、配列の値がTruthyのものだけ抽出していましたが、これは本来のArray.filter
メソッドと異なる挙動だったため修正しました。
それとあわせて、コールバック関数に何も記述しない場合に余計なプロパティまで取得していたのを修正しました。
--追記ここまで--
他所からお借りしたのでとりあえず無視してください。
以上、ES3(ExtendScript)でArray.filter
メソッドを使うコードでした。
*1:ExtendScriptでは、targetengineを定義するとそのエンジン内でprototype拡張することができます。「ESTKのtargetengineの挙動」を参照。
*2:Adobe「JavaScript Tool Guide CC(英文)」より、Chapter 8: ExtendScript Tools and Features, p234を参照。もしくはこちら。
*3:前掲注参照。