Les 5 forces arrivant sur le champ de bataille
Séance d'auto-introduction
pour
Je suis le Monde Traverse Le premier prince à apparaître, tout le monde ici doit m'appeler grand-père. Je peux répondre à la plupart des besoins des développeurs.
sont for
, foreach
, map
, for...in
, for...of
// 遍历数组 let arr = [1,2,3]; for(let i = 0;i < arr.length;i++){ console.log(i) // 索引,数组下标 console.log(arr[i]) // 数组下标所对应的元素 } // 遍历对象 let profile = {name:"April",nickname:"二十七刻",country:"China"}; for(let i = 0, keys=Object.keys(profile); i < keys.length;i++){ console.log(keys[i]) // 对象的键值 console.log(profile[keys[i]]) // 对象的键对应的值 } // 遍历字符串 let str = "abcdef"; for(let i = 0;i < str.length ;i++){ console.log(i) // 索引 字符串的下标 console.log(str[i]) // 字符串下标所对应的元素 } // 遍历DOM 节点 let articleParagraphs = document.querySelectorAll('.article > p'); for(let i = 0;i<articleParagraphs.length;i++){ articleParagraphs[i].classList.add("paragraph"); // 给class名为“article”节点下的 p 标签添加一个名为“paragraph” class属性。 }
forEach
Je suis la version ES5 libéré. La fonction de rappel est exécutée une fois pour chaque élément du tableau qui contient une valeur valide dans l'ordre croissant. Les éléments qui ont été supprimés ou non initialisés seront ignorés (comme sur les tableaux clairsemés). Je suis une version améliorée de la boucle for.
// 遍历数组 let arr = [1,2,3]; arr.forEach(i => console.log(i)) // logs 1 // logs 2 // logs 3 // 直接输出了数组的元素 //遍历对象 let profile = {name:"April",nickname:"二十七刻",country:"China"}; let keys = Object.keys(profile); keys.forEach(i => { console.log(i) // 对象的键值 console.log(profile[i]) // 对象的键对应的值 })
map
Je suis également publié en version ES5. Je peux créer un nouveau tableau. Le résultat du nouveau tableau est la valeur de retour après avoir appelé la fonction fournie une fois pour chaque élément du. tableau d'origine.
let arr = [1,2,3,4,5]; let res = arr.map(i => i * i); console.log(res) // logs [1, 4, 9, 16, 25]
pour...en énumération
J'ai sorti la version ES5. Parcourt les propriétés énumérables d'un objet, à l'exception du symbole, dans n'importe quel ordre.
// 遍历对象 let profile = {name:"April",nickname:"二十七刻",country:"China"}; for(let i in profile){ let item = profile[i]; console.log(item) // 对象的键值 console.log(i) // 对象的键对应的值 // 遍历数组 let arr = ['a','b','c']; for(let i in arr){ let item = arr[i]; console.log(item) // 数组下标所对应的元素 console.log(i) // 索引,数组下标 // 遍历字符串 let str = "abcd" for(let i in str){ let item = str[i]; console.log(item) // 字符串下标所对应的元素 console.log(i) // 索引 字符串的下标 }
pour...d'itération
J'ai sorti la version ES6. Créez une boucle d'itération sur un objet itérable (y compris Array, Map, Set, String, TypedArray, des objets arguments, etc.), invoquez un hook d'itération personnalisé et exécutez des instructions pour chaque valeur de propriété distincte.
// 迭代数组数组 let arr = ['a','b','c']; for(let item of arr){ console.log(item) } // logs 'a' // logs 'b' // logs 'c' // 迭代字符串 let str = "abc"; for (let value of str) { console.log(value); } // logs 'a' // logs 'b' // logs 'c' // 迭代map let iterable = new Map([["a", 1], ["b", 2], ["c", 3]] for (let entry of iterable) { console.log(entry); } // logs ["a", 1] // logs ["b", 2] // logs ["c", 3] // 迭代map获取键值 for (let [key, value] of iterable) { console.log(key) console.log(value); } // 迭代set let iterable = new Set([1, 1, 2, 2, 3, 3,4]); for (let value of iterable) { console.log(value); } // logs 1 // logs 2 // logs 3 // logs 4 // 迭代 DOM 节点 let articleParagraphs = document.querySelectorAll('.article > p'); for (let paragraph of articleParagraphs) { paragraph.classList.add("paragraph"); // 给class名为“article”节点下的 p 标签添加一个名为“paragraph” class属性。 } // 迭代arguments类数组对象 (function() { for (let argument of arguments) { console.log(argument); } })(1, 2, 3); // logs: // 1 // 2 // 3 // 迭代类型数组 let typeArr = new Uint8Array([0x00, 0xff]); for (let value of typeArr) { console.log(value); } // logs: // 0 // 255
Après la première série d'auto-introduction et de démonstration de compétences, nous avons appris :
L'instruction for est l'instruction de boucle la plus primitive. Définissez une variable i (type numérique, représentant l'indice du tableau) et effectuez une accumulation cyclique de i selon certaines conditions. La condition est généralement la longueur de l'objet boucle. Lorsque la longueur est dépassée, la boucle s'arrête. L'objet ne pouvant pas déterminer la longueur, il est utilisé avec Object.keys().
Proposé par forEach ES5. En prétendant être une version améliorée de l'instruction for, vous constaterez qu'elle est beaucoup plus simple à écrire que l'instruction for. Mais c'est essentiellement une boucle de tableaux. forEach exécute la fonction de rappel une fois pour chaque élément du tableau. C'est le tableau dans lequel il est appelé, donc le tableau d'origine ne sera pas modifié. La valeur de retour n'est pas définie.
carte proposée par ES5. Appelez la fonction de rappel une fois pour chaque élément du tableau d'origine dans l'ordre. Génère un nouveau tableau sans modifier le tableau d'origine à partir duquel il a été appelé. La valeur de retour est le nouveau tableau.
pour...en ES5 proposé. Parcourez les propriétés énumérables de l'objet, y compris les propriétés de l'objet prototype, et parcourez dans n'importe quel ordre, c'est-à-dire que l'ordre n'est pas fixe. Lors du parcours du tableau, l'indice du tableau est utilisé comme valeur clé. À ce stade, i est un type de chaîne. Il est conçu pour itérer sur les propriétés des objets et n'est pas recommandé pour une utilisation avec des tableaux.
pour...de ES6 proposé. Parcourez uniquement les données de l'objet itérable.
Identification des capacités
En tant que programmeur, il ne suffit pas de les connaître, il est nécessaire de les identifier réellement. développement. avantages et inconvénients. Utilisez-les en fonction des conditions locales, maximisez leurs points forts et évitez leurs faiblesses. C'est ainsi que réside la capacité d'améliorer les performances globales du programme.
À propos de sauter hors du corps de la boucle
Sortez du corps de la boucle lorsque certaines conditions sont remplies dans la boucle, ou ignorez les données qui ne remplissent pas les conditions et continuez à boucler d'autres données. C’est une exigence souvent rencontrée. Les instructions couramment utilisées sont break et continue.
Parlons brièvement de la différence entre les deux, juste pour examen.
L'instruction break consiste à sortir de la boucle actuelle et à exécuter l'instruction après la boucle actuelle ; l'instruction
continue consiste à terminer la boucle actuelle et continuer l'exécution. Une boucle ;
Remarque : forEach et map ne prennent pas en charge la sortie du corps de la boucle, mais les trois autres méthodes le font.
Principe : Si vous regardez le principe de mise en œuvre de forEach, vous comprendrez ce problème.
Array.prototype.forEach(callbackfn [,thisArg]{ }
La fonction transmise est la fonction de rappel ici. Il est définitivement illégal d'utiliser break dans une fonction de rappel, car break ne peut être utilisé que pour sortir d'une boucle et la fonction de rappel n'est pas le corps de la boucle.
L'utilisation de return dans la fonction de rappel renvoie uniquement le résultat à la fonction de niveau supérieur, c'est-à-dire cette boucle for, et ne termine pas la boucle for, donc return n'est également pas valide.
map() fonctionne de la même manière.
Appel en chaîne map()
La méthode map() peut être appelée dans une chaîne, ce qui signifie qu'elle peut être facilement utilisée en conjonction avec d'autres méthodes. Par exemple : réduire(), sort(), filtre(), etc. Mais d’autres méthodes ne peuvent pas y parvenir. La valeur de retour de forEach() n'est pas définie, elle ne peut donc pas être appelée dans une chaîne.
// 将元素乘以本身,再进行求和。 let arr = [1, 2, 3, 4, 5]; let res1 = arr.map(item => item * item).reduce((total, value) => total + value); console.log(res1) // logs 55 undefined"
for...in parcourra les propriétés de l'objet prototype
Object.prototype.objCustom = function() {}; Array.prototype.arrCustom = function() {}; var arr = ['a', 'b', 'c']; arr.foo = 'hello for (var i in arr) { console.log(i); } // logs // 0 // 1 // 2 // foo // arrCustom // objCustom
Cependant, dans le développement réel, nous n'avons pas besoin des propriétés de l'objet prototype. Dans ce cas, nous pouvons utiliser la méthode hasOwnProperty(), qui renvoie une valeur booléenne indiquant si l'objet possède la propriété spécifiée dans ses propres propriétés (c'est-à-dire s'il existe la clé spécifiée). Comme suit :
Object.prototype.objCustom = function() {}; Array.prototype.arrCustom = function() {}; var arr = ['a', 'b', 'c']; arr.foo = 'hello for (var i in arr) { if (arr.hasOwnProperty(i)) { console.log(i); } } // logs // 0 // 1 // 2 // foo // 可见数组本身的属性还是无法摆脱。此时建议使用 forEach
对于纯对象的遍历,选择for..in枚举更方便;对于数组遍历,如果不需要知道索引for..of迭代更合适,因为还可以中断;如果需要知道索引,则forEach()更合适;对于其他字符串,类数组,类型数组的迭代,for..of更占上风更胜一筹。但是注意低版本浏览器的是配性。
性能
有兴趣的读者可以找一组数据自行测试,文章就直接给出结果了,并做相应的解释。
for > for-of > forEach > map > for-in
for 循环当然是最简单的,因为它没有任何额外的函数调用栈和上下文;
for...of只要具有Iterator接口的数据结构,都可以使用它迭代成员。它直接读取的是键值。
forEach,因为它其实比我们想象得要复杂一些,它实际上是array.forEach(function(currentValue, index, arr), thisValue)它不是普通的 for 循环的语法糖,还有诸多参数和上下文需要在执行的时候考虑进来,这里可能拖慢性能;
map() 最慢,因为它的返回值是一个等长的全新的数组,数组创建和赋值产生的性能开销很大。
for...in需要穷举对象的所有属性,包括自定义的添加的属性也能遍历到。且for...in的key是String类型,有转换过程,开销比较大。
总结
在实际开发中我们要结合语义话、可读性和程序性能,去选择究竟使用哪种方案。
如果你需要将数组按照某种规则映射为另一个数组,就应该用 map。
如果你需要进行简单的遍历,用 forEach 或者 for of。
如果你需要对迭代器进行遍历,用 for of。
如果你需要过滤出符合条件的项,用 filterr。
如果你需要先按照规则映射为新数组,再根据条件过滤,那就用一个 map 加一个 filter。
总之,因地制宜,因时而变。千万不要因为过分追求性能,而忽略了语义和可读性。在实际开发中,让他们扬长避短,优势互补,让程序趋近最优才是我们要做的。
推荐教程:《JS教程》
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!