これは確かにV8のトリックです。 「プロパティ」JSが文字列インデックスを持つ属性であるが
JSObject
(JS Object
の内部C++表現)は、「要素」は、JS、数値インデックスを有する属性である2つの属性elements
とproperties
を有しています。
明らかに、プロパティ名を格納する必要がないため、数値インデックスのメモリ消費量ははるかに少なくなります。
http://code.google.com/intl/de-DE/chrome/devtools/docs/memory-analysis-101.html#primitive_objects
典型的なJavaScriptオブジェクトは、2つの配列posesses:名前付きプロパティを格納するための1つ、数値要素を格納するための別の。
これはV8のソースコードから見ることができます。
http://code.google.com/p/v8/source/browse/trunk/src/objects.h#1483
// [properties]: Backing storage for properties.
...
// [elements]: The elements (properties with names that are integers).
http://code.google.com/p/v8/source/browse/trunk/src/runtime.cc#4462
MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
Handle<Object> object,
Handle<Object> key,
Handle<Object> value,
PropertyAttributes attr,
StrictModeFlag strict_mode) {
...
// Check if the given key is an array index.
uint32_t index;
if (key->ToArrayIndex(&index)) {
// In Firefox/SpiderMonkey, Safari and Opera you can access the characters
// of a string using [] notation. We need to support this too in
// JavaScript.
// In the case of a String object we just need to redirect the assignment to
// the underlying string if the index is in range. Since the underlying
// string does nothing with the assignment then we can ignore such
// assignments.
if (js_object->IsStringObjectWithCharacterAt(index)) {
return *value;
}
Handle<Object> result = JSObject::SetElement(
js_object, index, value, attr, strict_mode, set_mode);
if (result.is_null()) return Failure::Exception();
return *value;
}
if (key->IsString()) {
Handle<Object> result;
if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
result = JSObject::SetElement(
js_object, index, value, attr, strict_mode, set_mode);
} else {
Handle<String> key_string = Handle<String>::cast(key);
key_string->TryFlatten();
result = JSReceiver::SetProperty(
js_object, key_string, value, attr, strict_mode);
}
if (result.is_null()) return Failure::Exception();
return *value;
}
// Call-back into JavaScript to convert the key to a string.
bool has_pending_exception = false;
Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
if (has_pending_exception) return Failure::Exception();
Handle<String> name = Handle<String>::cast(converted);
if (name->AsArrayIndex(&index)) {
return js_object->SetElement(
index, *value, attr, strict_mode, true, set_mode);
} else {
return js_object->SetProperty(*name, *value, attr, strict_mode);
}
}
私が詳細に入るが、SetObjectProperty
はどちらか呼び出すことに注意しませんSetElement
またはSetProperty
(キーによって異なります)。あなたのテストケースでチェックが失敗した理由はわかりませんkey = i + '0'
。