DRYな備忘録

Don't Repeat Yourself.

coffeeの for i in はJSの for(var i in ~) とは違うでござる!【CoffeeScript】【JavaScript】

【問題】

CoffeeScriptで以下のような処理を書いたんですね

getCap = (target, arr)->
  for i in arr
    if target < arr[i]
      return arr[i]

numbers = [1, 30, 35, 40, 80, 99]
console.log '30より大きいもので最も小さいもの', getCap(30, numbers) # 35を期待

で、出力

f:id:otiai10:20130310012009p:plain

あらーん? 最初はスコープの問題かとか思った

f:id:otiai10:20130310022704j:plain

【原因】

ドキュメントにiって書いてあったから当然indexだと勘違いしてた(;^ω^)

違います。arrの一要素です。

コンパイル後のJSを見てみると、

var getCap, numbers;
getCap = function(target, arr) {
  var i, _i, _len;
  for (_i = 0, _len = arr.length; _i < _len; _i++) {
    i = arr[_i];
    if (target < arr[i]) {
      return arr[i];
    }
  }
};
numbers = [1, 30, 35, 40, 80, 99];
return console.log('30より大きいもので最も小さいもの', getCap(30, numbers));

となってる。for i in arr のiにはarr[_i]が入ってる

【解決】

getCap = (target, arr)->
  for elm in arr
    if target < elm
      return elm

numbers = [1, 30, 35, 40, 80, 99]
console.log '30より大きいもので最も小さいもの', getCap(30, numbers) # 35を期待

出力

f:id:otiai10:20130310014255p:plain

とりあえずOK

ちなみに検証コードを書いてるときに、numbersが綺麗に連番だったりすると、ぱっと見ちゃんと(iがindexかのように)動いてるように見えて惑わされた(;^ω^)

【調査】

じゃーeach_with_indexみたいなんどうやってやんの?

なるほど for key,value of object ってのがあるのね

そもそもJavaScriptのArrayとObjectの勉強になった。

hoge = (target, arr)->
  for hash, value of arr
    if target < value
      obj = {}
      obj[hash] = value
      return obj

members =
  'john' : 1,
  'jack' : 30,
  'mary' : 35,
  'mike' : 40,
  'sam'  : 80,
  'kate' : 99

console.log '30より大きいもので最も小さいもの', hoge(30, members)
# Obj { "mary" : 35 } を期待

f:id:otiai10:20130310022251p:plain

おkいけてるぽい

obj ={} ってどうにかならんのかなぁ

【雑感】

保身のために書く。JavaScriptで for ( var i in arr) を foreachだと思って使ったら痛いメにあうよ。for(var i in arr) だとarrの全てのプロパティ(Array.ptorotype.hogeしたものやlengthなども含める)にアクセスするので、連想配列だと思ってると変なん混じるよ。

もうこんな時間でござる。

 

DRYな備忘録として