Front-end interview question bank ( necessary for interview) recommendation: ★★★★★
Address: front-end interview question bank
[National Day Avatar] - National Day patriotic programmer avatar! always one option fit for you!
for in
MDN description:
for...in
statement iterates over an object 's enumerable properties other than Symbol , including inherited enumerable properties, in any order.
Before I have a deep understanding of the role of for in, I only stay at the level where it can traverse object keys and array subscripts. Now let’s explore what is a Symbol type key in an object (newly added after ES6) and enumerable properties ,
Object types in JS include Object, Array, Function, Date, Math....
This article mainly uses Object and Array for practice
First, let's look at a piece of code:
const arr = [1, 2, 3, 4, 5];
const obj = {
mark: "mark-v",
jack: "jack-v",
amy: "amy-v",
};
for (const i in arr) { // 输出 0 1 2 3 4
console.log(i);
}
for (const i in obj) { // 输出 mark jack amy
console.log(i);
}
Presumably everyone knows the output result very well. If it is traversing the array, output the subscript corresponding to the array, and if it is traversing the object, output the key name of the object
Continue to add dishes, and then look at the following code:
const arr = [1, 2, 3, 4, 5];
arr.value = "array"; // 给数组对象上添加一个value属性
const s1 = Symbol("symbol1"); // 定义两个symbo类型的值
const s2 = Symbol("symbol2");
const obj = {
mark: "mark-v",
jack: "jack-v",
amy: "amy-v",
[s1]: "symbol1-v", // 给obj初始化这两个symbol键值
[s2]: "symbol2-v",
};
// 给obj原型上添加一个属性
Object.getPrototypeOf(obj).myProto = 'proto'
console.log(obj);
// 打印 {
// mark: 'mark-v',
// jack: 'jack-v',
// amy: 'amy-v',
// [Symbol(symbol1)]: 'symbol1-v',
// [Symbol(symbol2)]: 'symbol2-v'
// }
for (const i in arr) {
console.log(i); // 输出 0 1 2 3 4 value myProto
}
for (const i in obj) {
console.log(i); // 输出 mark jack amy myProto
}
As can be seen from the above output results, whether it is an array element or a key value on an object, it is an enumerable attribute , and it can be seen that the key of the Symbol type is defined in the object, but for in will skip the Symbol type key traversal
And for in will also traverse the prototype chain , so why both obj and arr will output 'myProto', that is because obj is an object, the default constructor is Object(), and arr is an array object, the default The constructor is Array(), but the prototype property of Array is essentially an object, so the prototype of the Array prototype is the prototype property on Object
Object.getPrototypeOf(obj) === Object.getPrototypeOf(Object.getPrototypeOf(arr)) // true
So the prototype chains of arr and obj have an intersection point, which explains that they can all traverse to myProto
We can also simply think that the attribute corresponding to the Symbol type key in an object is not an enumerable attribute, but in fact it is still an enumerable attribute, but it is skipped. This passage is a bit confusing, but in the past It will be clear when you look down.
Since the traversal of for in cannot bypass enumerable attributes, what is an enumerable attribute? The explanation of MDN is as follows:
Enumerable properties refer to those properties whose internal "enumerable" flag is set to
true
. For properties through direct assignment and property initialization, the flag value defaults to thattrue
. For properties defined through Object.defineProperty , etc., the flag The value defaults tofalse
. Enumerable properties can be traversed through a for...in loop (unless the property name is a Symbol ). Property ownership is determined by judging whether the property directly belongs to an object, rather than being inherited through the prototype chain.
From the above it can be concluded that,
- Enumerable properties are those inside an object that have the "enumerable" flag set to true
- For properties defined by literals, the enumerable flag defaults to true, and for properties defined by Object.defineProperty, etc., the flag defaults to flase
- The for in loop only traverses the enumerable properties in the object, and skips properties whose property names are of type Symbol
- for in will only traverse the enumerable properties on the object itself
Please see the following code:
const s1 = Symbol("symbol1");
const s2 = Symbol("symbol2");
// 以下字面量初始化和赋值的属性可枚举标识都为true
const obj = { // 方式一
mark: "mark-v",
};
obj.jack = "jack-v" // 方式二
obj['amy'] = 'amy-v' // 方式三
Object.defineProperty(obj, "kong", {
value: "kong-v",
enumerable: false, // 可枚举标识,默认为 false
});
Object.defineProperty(obj, "john", {
value: "john-v",
enumerable: true, // 设置为 true
});
// 通过Object.defineProperty设置Symbol类型键
Object.defineProperty(obj, s1, {
value: "s1-v",
enumerable: false,
});
// 通过Object.defineProperty设置Symbol类型键,并且可枚举标识为true
Object.defineProperty(obj, s2, {
value: "s2-v",
enumerable: true,
});
console.log(obj);
// 打印 {
// mark: 'mark-v',
// jack: 'jack-v',
// amy: 'amy-v',
// john: 'john-v',
// [Symbol(symbol2)]: 's2-v'
// }
for (const i in obj) {
console.log(i); // 输出 mark jack amy john
}
In the above code, we first created an obj object with an initialization property mark, then defined two new properties through literals, and defined 2 key values of string type and 2 symbol types through Object.defineProperty, both Each has an enumerable and non-enumerable identifier
You can see that the console.log prints obj, which only contains enumerable attributes, that is to say, the attribute whose enumerable flag is false will not appear in the printed content of the entire obj object, which also verifies that even if the Symbol type key The attribute can be enumerated as true, and it will also be skipped by for in.
Additional expansion
const arr = [1, 2, 3, 4, 5];
// 设置arr对象属性0的值为100,不可枚举,不可修改
Object.defineProperty(arr, 0, {
value: 100,
enumerable: false,
writable: false,
});
arr[0] = 1 // 尝试修改下标0的值
console.log(arr); // 打印 [ 100, 2, 3, 4, 5 ]
for (const i in arr) {
console.log(i); // 输出 1 2 3 4
}
You can see that the subscript of the array is also an attribute of the array object. After setting the subscript 0 to be non-enumerable and non-modifiable, for in cannot traverse the subscript 0, and cannot modify the value of the subscript 0, but the fun thing is to print Arrays will still print out each element in its entirety.
for of
MDN description:
for...of
The statement creates an iteration loop over iterable objects (including Array , Map , Set , String , TypedArray , arguments objects, etc.), calls custom iteration hooks, and executes the statement for the value of each distinct property
for of is a new ES6 syntax for traversing iterable objects (implementing the Iterator interface)
example
// 迭代数组
const array = [10, 20, 30];
for (const value of array) {
console.log(value); // 输出 10 20 30
}
// 迭代String
const string = 'kong'
for (const s of string) {
console.log(s); // 输出 k o n g
}
// 迭代map
const map = new Map([["a", 1], ["b", 2], ["c", 3]]);
for (const item of map) {
console.log(item); // 输出 [ 'a', 1 ] [ 'b', 2 ] [ 'c', 3 ]
}
// 迭代set
const set = new Set([1, 1, 2, 2, 3, 3]);
for (let item of set) {
console.log(item); // 输出 1 2 3
}
close iterator
For for...of
loops, it can be terminated by break
, throw
or return
. In these cases, the iterator is closed.
return situation
const array = [10, 20, 30];
for (const value of array) {
console.log(value); // 输出 10
return
}
// 下面代码不会执行,前面已经return
const string = 'kong'
for (const s of string) {
console.log(s);
}
Throw situation
const array = [10, 20, 30];
for (const value of array) {
console.log(value); // 输出 10
throw new Error()
}
// 不执行下面代码,上面已经抛错
const string = "kong";
for (const s of string) {
console.log(s);
}
For for...in
the loop, the above interrupt method is also applicable
Summarize
for...in
Applicable to the traversal of enumerable properties on objects , and only traverse non-Symbol type keys and enumerable properties on the object itself and the prototype chainfor...of
Applicable to the traversal of objects (also known as iterable objects) that implement the Iterator interface . The traversal method is implemented by itself. For example, for an array, it is to traverse the value of each element corresponding to its subscript, and for a Map, the traversal value is composed of key-value pairs array of
Front-end interview question bank ( necessary for interview) recommendation: ★★★★★
Address: front-end interview question bank
[National Day Avatar] - National Day patriotic programmer avatar! always one option fit for you!