taiyoh's memorandum

@ttaiyoh が、技術ネタで気づいたことを書き溜めておきます。

typeofを使わずに配列かどうかを判別(ただし失敗)

 jsdo.itユーザのtsmallfieldさんから以下のお題が出た。

(本物の)配列かどうかを判断するのに

var isArray = function(arg){
  return [].concat(arg)[0] !== arg;
};

ではどうだろう?とふと思ついたのでテスト。

http://jsdo.it/tsmallfield/isArray

 10分ほど考えて、これが失敗するコードを作成

var a = [];
a[0] = a;

isArray(a); // => false

 Array#concatで、配列でないものは配列の0番目に、そうでないものは頭からマージされるので、それの0番目を取り出して元々のオブジェクトと比較すれば、同じオブジェクトが返ってくるということは配列でない、という論理。ただしJavaScriptのオブジェクトの場合、この手の比較は実質アドレス値の比較になるので、循環参照して0番目に同じアドレスが入るようにしておくと、同じアドレス値同士での比較になってしまい、偽値が返却されてしまう。