疑問メモ: 配列をObject.createすると何が失われるのか、pushは何をするのか
JavaScriptの本を読んでいて理解できない点があったのでメモします。
3章で紹介したObject.createメソッドを、配列に対して使うことはおすすめできない。なぜなら戻り値が配列ではなく、単なるオブジェクトになってしまうからだ。生成されたオブジェクトは元の配列の要素の値とメソッドを継承はするが、lengthプロパティという配列の持つ特殊な性質が失われてしまう。
Douglas Crockford:『JavaScript: The Good Parts』,,p.73,オライリー・ジャパン,2008.12.
「lengthの性質が失われる」って、どんな性質が失われるのでしょうか。よくわかりません。
テストA: 配列のlength番目の要素に値を代入してみる
var assert = require('assert'); describe('prototype', function(){ it('6.6 配列のlength番目の要素に値を代入すると、lengthがインクリメントされる。', function(){ var data = [4, 8, 15, 16, 23, 42]; assert(data.length === 6); data[data.length] = 1; assert(data.length === 7); }) }); describe('prototype', function(){ it('6.6 オブジェクトの(変数)lengthという名前のプロパティに値を代入しても、lengthの値はインクリメントされない。', function(){ var data = [4, 8, 15, 16, 23, 42]; // a value which is got from Object.create is just a object var foo = Object.create(data); assert(foo.length === 6); foo[foo.length] = 1; // This is NOT Array.length assert(foo.length === 6); // 6 is name of property assert(foo[6] === 1); }) });
2つ目のテストにある変数fooは、配列でなく単なるオブジェクトになるそうです。
もしlengthの性質が「要素のインデックスの最大値+1を指す」ことだとすれば、たしかにそれは失われてしまったようです。
テストB: 値をpushしてみる
var assert = require('assert'); describe('prototype', function(){ it('6.6 配列に値をpushすると、lengthがインクリメントされる。', function(){ var data = [4, 8, 15, 16, 23, 42]; assert(data.length === 6); data.push(1); assert(data.length === 7); }) }); describe('prototype', function(){ it('6.6 オブジェクトに値をpushすると、lengthがインクリメントされる??', function(){ var data = [4, 8, 15, 16, 23, 42]; // a value which is got from Object.create is just a object var foo = Object.create(data); assert(foo.length === 6); foo.push(1); // This is NOT Array.length assert(foo.length === 7); }) });
上のようにpushを使った場合は、lengthの「要素のインデックスの最大値+1を指す」性質が、Object.createをしたのに維持されているように見えます。
- ここでいうlengthの性質とは、「要素のインデックスの最大値+1を指す」こと、でよいのか?
- pushはArrayだけでなくオブジェクトにも使えるのか、使っていいのか
- pushの仕組みはどのコードで確認するのか(標準ライブラリ??)
といったあたりが分かりません。。。分かったら続きを書く予定。