質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.61%

  • JavaScript

    15996questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

javascriptで連想配列がforeach出来ない

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 1,342

tesopgmh

score 85

「a:1,b:2,c:3」こういった文字列を連想配列に変換する関数hugaを作ったのですが
連想配列に変換した値をforEachするとなにも起きません

期待する結果
1
2
3

実際の結果
<なにもない>

valsをconsole.dirすると

a: "1"
b: "2"
c: "3"

となっているので連想配列への変換はうまくいっているようなのですが
なぜforEach内のプログラムが実行されないのでしょうか

分かる方お教えくださいませ

var vals = huga('a:1,b:2,c:3');
vals.forEach(function(value,key){
  console.log(value);
});

function huga(str){

  arr = [];
  arr2 = [];
  arr = str.split(',');

  var i = 1;
  arr.forEach(function(value,key){

      var tmp_arr = [];
      tmp_arr = value.split(':');
      key = tmp_arr[0];
      value = tmp_arr[1];

      arr2[key] = value;

  });

  return arr2;

}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+6

Array.prototype.forEach数値プロパティのみ参照するようになっているので、配列に無理やりarr['a'] = 'b';のようなものを代入しても、それは単に無視されます。

普通のオブジェクトに入れて、Object.keysでキーリストを取得する、あるいはfor-inを使う、などの手段が必要です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/12 10:31

    なるほど!forEachは数値しか見てくれないんですね
    Javascriptは素晴らしい言語ですがたまに他の言語で当たり前に出来ることが出来なくてビックリすることがあります

    キャンセル

  • 2017/12/12 10:36

    for-inでうまくいきました!ありがとうございます!

    キャンセル

+4

 数値添字配列

JavaScriptの配列は数値添字配列であり、文字列添字配列に対応していないからです。
文字列添字配列が必要な場合は、次のいずれかを使用する事になります。

  • オブジェクト初期化子({})
  • Object.create(null)
  • new Map

 new Map

Map には Map.prototype.forEach があるので、比較的扱いやすいといえます。

'use strict';
function foo (string) {
  var array = string.split(',');

  for (var i = 0, len = array.length; i < len; ++i) {
    array[i] = array[i].split(':');
  }

  return new Map(array);
}

var map = foo('a:1,b:2,c:3');

console.log(map.get('a'));                        // 1
console.log(JSON.stringify([...map.entries()]));  // [["a","1"],["b","2"],["c","3"]]

map.forEach((value, key) => console.log(value, key));

 Object.create(null)

Object.create(null) は {} とほぼ等価ですが、プロトタイプ上にオブジェクトが存在しない為、__proto__ 等の規定値となる名前もキー名に出来るメリットがあります。

'use strict';
function foo2 (string) {
  var object = Object.create(null);

  for (var i = 0, array = string.split(','), len = array.length, entry; i < len; ++i) {
    entry = array[i].split(':');
    object[entry[0]] = entry[1];
  }

  return object;
}

var object = foo2('a:1,b:2,c:3');

console.log(object.a);  // 1
Object.keys(object).forEach(key => console.log(key, object[key]));

Re: tesopgmh さん

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/12 10:33

    文字列添字配列に対応していないというのはどういうことですか?普通に使えますけど??
    歴史的に昔はそうであったということですか?ググってみたのですが出てきませんでした

    mapの使い方ありがとうございます!!

    キャンセル

  • 2017/12/12 12:34 編集

    例えば、var array = []; を定義した場合、array.a = 1; で要素を増やしても array.length は増えませんし、array.forEach で走査することも出来ません。つまり、文字列をキーにしても配列独自の機能が使えません。
    for-inやObject.keysが有効なのは、配列がオブジェクトでもあり、オブジェクトのプロパティ列挙機能でキーの列挙を代用しているためです。
    しかし、ただのオブジェクトとしての扱いとなるため、定義順で列挙される保証がなく、lengthのように配列の要素数を数える機能もありません(Object.keys(array).lengthで代用可)。
    文字列をキーにする限りでは、{} と [] はほぼ等価です。
    また、array.lengthのような予約済みのプロパティに任意の文字列値を与えることも不可能であり、その点では、Object.create(null) が勝ります。
    諸々の問題を全てを解決したのが new Map となります。

    キャンセル

+2

上記を御覧ください、ArrayにはArray.prototype.forEachがありますが、
ObjectにはObject.prototype.forEachなるメソッドは存在しません。
というわけで無いものはないのだ!

どうすんねん?

上記のメソッドを経由して使いましょう。
ES5対応のObject.keysが第一選択肢となります。
次点はfor...of構文ですね、ただしこちらは殆どのブラウザに採用されているとはいえES2015なのでIE11では使えない事に注意してください。
本来ならばvaluesやentitiesが便利なのですがES2015専用だし対応ブラウザはChromeくらいしかありません。

質問文からはこうすれば通るかと思います。

var vals = huga('a:1,b:2,c:3');
Object
  .keys(vals)
  .forEach(function(key){
    console.log(value);
  });

【おまけ】普通のオブジェクトをつくる

オブジェクトじゃないじゃないか!
こっちも私の勝手に作っちゃうんだからね!!

function huga (str) {
  return str
    .split(',')
    .map(function(it){ return it.split(':'); })
    .reduce(function(obj, it){
      obj[it[0]] = it[1];
      return obj;
    }, {});
}
var vals = huga('a:1,b:2,c:3');
console.log(vals);
// Object { a: "1", b: "2", c: "3" }

これなら私の回答文のはじめの状態から使えると思うから試してみてね。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/12 10:35

    丁寧にありがとうございます!こんな書き方もあるんですね
    Javascriptは同じ処理でもいろいろな関数や書き方が混在していてとてもユニークですね

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • JavaScript

    15996questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。