🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
JavaScript

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

Q&A

解決済

1回答

808閲覧

javascriptのArray.prototype.pushをオブジェクトに使った時のlengthプロパティについて

moriman

総合スコア615

JavaScript

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

0グッド

2クリップ

投稿2019/10/03 00:52

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/push

javascript

1let obj = { 2 length: 0, 3 4 addElem: function addElem (elem) { 5 // obj.length は、要素が追加されるたびに自動的に増分する。 6 Array.prototype.push.call(this, elem); 7 } 8}; 9 10// 例示のために空のオブジェクトを追加する。 11obj.addElem({}); 12obj.addElem({}); 13obj.addElem({}); 14 15console.log(obj.length); 16// → 3 17console.log(obj); 18// → {0: {…}, 1: {…}, 2: {…}, length: 3, addElem: f} 19console.log('--------------------------'); 20let obj_1={ 21 length : 0 22} 23 24obj_1.prop_1='prop_1'; 25 26console.log(obj_1.length); 27// 0 28console.log(obj_1); 29// {length: 0, prop_1: "prop_1"}

mdnのサンプルなんですが、まず前回の質問と同じで、addElemの中で
Array.prototype.push.call(this, elem);
としているのですが、これで
addElemを実行する度にobjにプロパティが追加されるのがなぜなのか?
なぜthisをobjに固定すると、オブジェクトであるobjにプロパティを追加できるのか?
と思ってしまうのですが、これは、pushがそういう風に作られているから、と理解しておくのが良いでしょうか?
というか、オブジェクトに対してArray.prototype.pushを使用する方法が上記の方法だ、という理解で問題ないでしょうか?

次に上記のサンプルの前半(----------------)よりも上の部分。でaddElemを実行する度にlengthプロパティが増えていくのですが、これは何の働きでこうなるのでしょうか。
objのlengthプロパティは組み込みで最初から用意されているのではなく、プログラマが勝手に用意したプロパティだと思うのですが、上記のコードだけで当然のようにlengthが増えているのがかなり不自然に思えます。

試しに上記サンプルの後半のように、自分でlengthプロパティを持ったオブジェクトobj_1を作って、obj_1に対してプロパティprop_1を追加してもlengthプロパティは0のままです。

あと上記mdnのページの中で

push はジェネリックメソッドとして用意されています。そのため call() や apply() と一緒にオブジェクトに対して利用することもできます。

と説明があるのですが、ジェネリックメソッドとは何ですか?

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

まず、 Array.prototype.push()の使い方として一般的には以下のように使います。

javascript

1var arr = []; 2arr.push(1); 3arr.push(2); 4 5console.log(arr) // [1, 2]

Array.prototype.push()メソッドは内部でthis に対して要素を追加するという処理をしています。
また関数オブジェクトが持つ .call() メソッドは関数を実行する際のthis を指定できます。
その為、Array.prototype.push.call()メソッドで this にオブジェクトを指定すると、そのオブジェクトに対して要素が追加されるという動作になります。
このようなメソッドの処理の対象を引数で指定できるメソッドをジェネリックメソッドと呼んでいます。

.push()メソッドでは配列風のオブジェクトに対して要素を追加することができるので、Object等をthisに指定しても概ね動作するのですが、基本的にはArrayオブジェクトの為のメソッドであり、Arrayオブジェクトが持つ配列長を格納するlengthプロパティに対して値を増分する処理を行います。プロパティがなければ作成されます。
もう少し補足しますと、.push()メソッドの実行時、まずlengthプロパティを参照し、その値をキーとして要素を追加します。lengthプロパティがない場合のキーは 0です。その為以下のような動きになります。

javascript

1obj = { 2 0: 'foo', 3 length: 1 4} 5 6Array.prototype.push.call(obj, 'bar'); 7 8console.log(obj); // {0: "foo", 1: "bar", length: 2}

個人的にはArrayオブジェクト以外で Array.prototype.push() は使わない方が良いと思います。

投稿2019/10/03 02:00

編集2019/10/03 02:13
foobar810

総合スコア217

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

miyabi_takatsuk

2019/10/03 02:15 編集

横やりすみません。 > 個人的にはArrayオブジェクト以外で Array.prototype.push() は使わない方が良いと思います。 これ禿同ですね。 他言語でいう連想配列調オブジェクトはあくまでその型で扱いその中で処理するのが妥当だと私も思います。そのためかわからないですが、Object.keysやObject.entriesがありますしね。 JSって型厳密じゃないから、拡張しないでこういうことできちゃうけど、 他の言語じゃ通じないですしね。
moriman

2019/10/04 01:30

解答を頂きましてありがとうございました。よくわかりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問