htsign's blog

ノンジャンルで書くつもりだけど技術系が多いんじゃないかと思います

JScript(not JavaScript)のArrayに対するメソッド群を追加する超単純なポリフィル

今さらこんなコードを書くこと自体恥ずべきことだと思うのだけど、勤務先の業務システムがJSPで実装されており、クライアントサイドはレガシーなIEが想定されています(嘆かわしいですが、よくある光景ですね…)

そしてこれまたよくある光景なのですが、秘伝のソースであるため、

<%-- yyyy/mm/dd add someone IE11対応 --%>
<META HTTP-EQUIV=X-UA-Compatible CONTENT=IE=5>
<%-- /IE11対応 --%>

みたいなのが書いてあるわけです。
お前それどこがIE11対応やねん、といったツッコミはさておき。

そんな環境ですと、おもむろにF12を押してデバッグをしようにも配列やArrayLikeを扱う上で非常につらみを感じるわけです。
「じゃあlodash使えばいいじゃん!」と

(function(s){
  s.src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js";
  document.body.appendChild(s);
})(document.createElement("script"))

なんてコードを実行してみても、lodashの実行中にコケたりするんです。
そのときに知ったんですが、lodashってIE9+なんですね…。

便利なライブラリが使えないとなると、ある程度自分で書かざるをえないのでブックマークレットを作成して活用しています。

というのが前置き。
当たり前ですがコードの持ち出しは禁止なので、実際のコードとはちょっと違うと思います。

javascript:(function(d,i,l,x,a){d("indexOf",function(v){for(i=0,l=this.length;i<l;++i)if(this[i]===v)return i;return -1});d("includes",function(v){return!!~this.indexOf(v)});d("map",function(f,t){x=this,a=[];for(i=0,l=x.length;i<l;++i)a.push(f.call(t,x[i],i,x));return a});d("filter",function(f,t){x=this,a=[];for(i=0,l=x.length;i<l;++i)f.call(t,x[i],i,x)&&a.push(x[i]);return a});d("forEach",function(f,t){x=this;for(i=0,l=x.length;i<l;++i)f.call(t,x[i],i,x)});d("reduce",function(f,v){x=this,v=v!==void 0?v:x.shift();for(i=0,l=x.length;i<l;++i)v=f(v,x[i],i,x);return v});d("every",function(f,t){return!!this.reduce(function(p,c){return p&&f.call(t,c)},1)});d("some",function(f,t){return!!this.reduce(function(p,c){return p||f.call(t,c)},0)})})(function(n,f){if(![][n])Array.prototype[n]=f})

追記 (2018/06/11 01:59)

改めてGistに起こしました。
ES5 or above polyfills for ES3 (It's not compatible with ECMA-262 strictly) · GitHub

lenという変数を定義してまでいちいちthis.lengthを代入している理由は、賢明な諸兄はもちろんご存知かと思いますが、forループで毎回Array#lengthにアクセスしてパフォーマンスが落ちるからです。
なので最初に長さを持ってしまいます。
その結果、高階関数に渡す関数がオブジェクト自身の要素数に副作用を起こすものである場合、意図しない動作になります。

まぁ自分しか使わないのでどうでもいいんですが。