enumerable は forEach 系に関係ない
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 0
◆ enumerable の列挙するかは for in など一部でのみ関係する
◆ Object.keys で組み込みのメソッドやプロパティが見えないのは enumerable 見えないから
◆ 配列の length とか
◆ forEach はプロトタイプチェーンの先でもプロパティあると実行される
◆ Object.keys で組み込みのメソッドやプロパティが見えないのは enumerable 見えないから
◆ 配列の length とか
◆ forEach はプロトタイプチェーンの先でもプロパティあると実行される
いまだに enumerable のスペルに自信のない私ですが 今回は enumerable 使ってみます
ときどきスペルが間違ってるかもしれませんがご容赦ください
o2 ---> o1 にプロトタイプチェーンをつないでます
enum って列挙型で使われますし それの able 系ですので列挙されるかどうかを表してるんですね
__proto__ や constructor や 各 prototype にあるメソッドは enumerable が false です
enumerable が false だと Chrome だと薄く表示してくれます

enumerable が false のプロパティを作ってみます
ドキュメントを見たわけじゃないですが たぶん forEach 系の中身ってこんなのなんだと思います
for in だと enumerable = false は無いもの扱いなのにただの in だと enumerable = false でもあるもの扱いされるようです
んー わかりづらいー
とりあえず関係しそうなのをまとめてみました
own property 系は名前の通り プロトタイプチェーンは見ないで自分自身が対象です
enumerable は気にせずあるものはあるって返って来ます
propertyIsEnumerable はそのプロパティが enumerable か教えてくれます
存在しなかったり プロトタイプチェーンの先にある場合は false です
一覧取得系でプロトタイプチェーンも見て enumerable = false も持ってくるのが無いです
キーがわからない状態で取得するなら手動でチェーンたどるしか無いのかなー
それぞれの結果と使い方はこんなになります
ときどきスペルが間違ってるかもしれませんがご容赦ください
for in
まず 普通に for in をしてみますo2 ---> o1 にプロトタイプチェーンをつないでます
var o1 = {x:10}
var o2 = {a:1, __proto__:o1}
for(var i in o2) console.log(i)
// a x
o1 に enumerable を true と false でプロパティを追加しますvar o2 = {a:1, __proto__:o1}
for(var i in o2) console.log(i)
// a x
Object.defineProperty(o1, "y", {enumerable:false, value:20})
o2.y
// 20
Object.defineProperty(o1, "z", {enumerable:true, value:30})
o2.z
// 30
for(var i in o2) console.log(i)
// a x z
for in では enumerable = false で追加した y が見えていませんo2.y
// 20
Object.defineProperty(o1, "z", {enumerable:true, value:30})
o2.z
// 30
for(var i in o2) console.log(i)
// a x z
enum って列挙型で使われますし それの able 系ですので列挙されるかどうかを表してるんですね
__proto__ や constructor や 各 prototype にあるメソッドは enumerable が false です
enumerable が false だと Chrome だと薄く表示してくれます

forEach
じゃあ つぎは配列メソッドvar a1 = [1,2]
var a2 = new Array(5)
a2[0] = 10
a2.__proto__ = a1
a2.forEach(e=>{console.log(e)})
// 10 2
プロトタイプチェーンの先の 2 も表示されていますvar a2 = new Array(5)
a2[0] = 10
a2.__proto__ = a1
a2.forEach(e=>{console.log(e)})
// 10 2
enumerable が false のプロパティを作ってみます
Object.defineProperty(a1, "3", {enumerable:false, value:3})
a2.forEach(e=>{console.log(e)})
// 10 2 3
表示されていますねa2.forEach(e=>{console.log(e)})
// 10 2 3
ドキュメントを見たわけじゃないですが たぶん forEach 系の中身ってこんなのなんだと思います
Array.prototype.forEach = function(cb){
for(var i = 0, l = this.length; i < l; i++) i in this && cb(this[i], i, this)
}
in でオブジェクトとしてキーがあるかだけを見て enumerable かどうかなんて気にしないですfor(var i = 0, l = this.length; i < l; i++) i in this && cb(this[i], i, this)
}
for in だと enumerable = false は無いもの扱いなのにただの in だと enumerable = false でもあるもの扱いされるようです
んー わかりづらいー
とりあえず関係しそうなのをまとめてみました
プロトタイプ チェーン | enumerable | 取得方法 | |
in | 見る | false も | 指定したプロパティに対して true, false |
for in | 見る | true だけ | 指定したオブジェクトをループで全部のキー |
obj .hasOwnProperty | 見ない | false も | 指定したプロパティに対して true, false |
Object .getOwnPropertyNames | 見ない | false も | 指定したオブジェクトのキー全部を配列で |
Object.keys | 見ない | true だけ | 指定したオブジェクトのキー全部を配列で |
obj .propertyIsEnumerable | 見ない | false も | 指定したプロパティに対して true, false |
arr.forEach | 見る | false も | 数値のキーのみループで |
own property 系は名前の通り プロトタイプチェーンは見ないで自分自身が対象です
enumerable は気にせずあるものはあるって返って来ます
propertyIsEnumerable はそのプロパティが enumerable か教えてくれます
存在しなかったり プロトタイプチェーンの先にある場合は false です
一覧取得系でプロトタイプチェーンも見て enumerable = false も持ってくるのが無いです
キーがわからない状態で取得するなら手動でチェーンたどるしか無いのかなー
それぞれの結果と使い方はこんなになります
var obj = {}
Object.defineProperty(obj, "not_enum", {enumerable:false, value:true})
Object.defineProperty(obj, "enum", {enumerable:true, value:true})
var proto = {}
Object.defineProperty(proto, "proto_not_enum", {enumerable:false, value:true})
Object.defineProperty(proto, "proto_enum", {enumerable:true, value:true})
obj.__proto__ = proto
console.log("enum" in obj) // true
console.log("not_enum" in obj) // true
console.log("proto_enum" in obj) // true
console.log("proto_not_enum" in obj) // true
for(var _ in obj) console.log(_)
// enum
// proto_enum
console.log(obj.hasOwnProperty("enum")) // true
console.log(obj.hasOwnProperty("not_enum")) // true
console.log(obj.hasOwnProperty("proto_enum")) // false
console.log(obj.hasOwnProperty("proto_not_enum")) // false
console.log(Object.getOwnPropertyNames(obj))
// [not_enum, enum]
console.log(Object.keys(obj))
// [enum]
Object.defineProperty(obj, "not_enum", {enumerable:false, value:true})
Object.defineProperty(obj, "enum", {enumerable:true, value:true})
var proto = {}
Object.defineProperty(proto, "proto_not_enum", {enumerable:false, value:true})
Object.defineProperty(proto, "proto_enum", {enumerable:true, value:true})
obj.__proto__ = proto
console.log("enum" in obj) // true
console.log("not_enum" in obj) // true
console.log("proto_enum" in obj) // true
console.log("proto_not_enum" in obj) // true
for(var _ in obj) console.log(_)
// enum
// proto_enum
console.log(obj.hasOwnProperty("enum")) // true
console.log(obj.hasOwnProperty("not_enum")) // true
console.log(obj.hasOwnProperty("proto_enum")) // false
console.log(obj.hasOwnProperty("proto_not_enum")) // false
console.log(Object.getOwnPropertyNames(obj))
// [not_enum, enum]
console.log(Object.keys(obj))
// [enum]