Les boucles for dans es6 sont similaires : 1. boucle "for-in", les objets qu'elle traverse ne sont pas limités aux tableaux, mais peuvent également traverser des objets, la syntaxe est "for (nom de clé dans l'objet) {... }"; 2. Boucle ForEach, exécutez la fonction de rappel une fois pour chaque élément du tableau qui contient une valeur valide, la syntaxe est "array.forEach(callback function, thisValue)"; 3. Boucle "for-of", la la syntaxe est "pour (valeur actuelle du tableau){...}".
L'environnement d'exploitation de ce tutoriel : système Windows 7, ECMAScript version 6, ordinateur Dell G3.
ECMAScript6 (ES6 en abrégé) prend en charge 4 types de boucles for.
Boucle for simple
for-in
forEach
for-of
Jetons un coup d'œil à ces 4 types de boucles for.
Jetons un coup d'œil à la méthode d'écriture la plus courante :
const arr = [1, 2, 3]; for(let i = 0; i < arr.length; i++) { console.log(arr[i]); }
Lorsque la longueur du tableau ne change pas pendant la boucle, nous devons stocker la longueur du tableau dans une variable . Cela permettra d'obtenir une meilleure efficacité. Voici la façon d'écrire améliorée :
const arr = [1, 2, 3]; for(let i = 0, len = arr.length; i < len; i++) { console.log(arr[i]); }
Normalement, nous pouvons utiliser for-in pour parcourir le contenu du tableau. :
const arr = [1, 2, 3]; let index; for(index in arr) { console.log("arr[" + index + "] = " + arr[index]); }
Dans des circonstances normales, les résultats en cours d'exécution sont les suivants :
Mais cela pose souvent des problèmes. La vérité sur la boucle
for-in
for-in traverse les propriétés de l'objet, pas l'index du tableau. Par conséquent, les objets traversés par for-in ne se limitent pas aux tableaux, mais peuvent également traverser des objets. Un exemple est le suivant :
const person = { fname: "san", lname: "zhang", age: 99 }; let info; for(info in person) { console.log("person[" + info + "] = " + person[info]); }
Le résultat est le suivant :
Il convient de noter que l'ordre dans lequel for-in parcourt les attributs n'est pas déterminé, c'est-à-dire que l'ordre des résultats de sortie n'a rien rien à voir avec l'ordre des attributs dans l'objet, ni avec l'ordre alphabétique des attributs. Non pertinent, pas dans un autre ordre.
La vérité sur Array
Array est un objet en Javascript, et l'index de Array est le nom de la propriété. En fait, "tableau" en Javascript est quelque peu trompeur. Le tableau en Javascript n'est pas comme les tableaux dans la plupart des autres langages. Tout d'abord, Array en Javascript n'est pas continu en mémoire. Deuxièmement, l'index de Array ne fait pas référence au décalage. En fait, l’index de Array n’est pas de type Number, mais de type String. La raison pour laquelle nous pouvons utiliser correctement arr[0] est que le langage peut automatiquement convertir 0 de type Number en "0" de type String. Par conséquent, il n'y a jamais d'index Array en Javascript, mais uniquement des propriétés telles que "0", "1", etc. Il est intéressant de noter que chaque objet Array possède une propriété length, ce qui le fait se comporter davantage comme des tableaux dans d'autres langages. Mais pourquoi l'attribut length n'est-il pas affiché lors du parcours de l'objet Array ? En effet, for-in ne peut parcourir que des "propriétés énumérables", la longueur est une propriété non énumérable et, en fait, les objets Array ont de nombreuses autres propriétés non énumérables.
Maintenant, revenons en arrière et regardons l'exemple d'utilisation de for-in pour boucler un tableau. Modifions l'exemple précédent de parcours du tableau :
const arr = [1, 2, 3]; arr.name = "Hello world"; let index; for(index in arr) { console.log("arr[" + index + "] = " + arr[index]); }
Le résultat exécuté est :
Nous voyons que le boucle for-in Notre nouvelle propriété "name" est accessible car le for-in parcourt toutes les propriétés de l'objet, pas seulement "l'index". Dans le même temps, il convient de noter que les valeurs d'index sorties ici, c'est-à-dire "0", "1" et "2", ne sont pas de type Number, mais de type String, car elles sont sorties en tant qu'attributs. , pas les index. Cela signifie-t-il que nous pouvons simplement afficher le contenu du tableau sans ajouter de nouvelles propriétés à notre objet Array ? La réponse est non. Parce que for-in ne parcourt pas seulement les propriétés du tableau lui-même, il parcourt également toutes les propriétés énumérables de la chaîne de prototypes du tableau. Regardons un exemple ci-dessous :
Array.prototype.fatherName = "Father"; const arr = [1, 2, 3]; arr.name = "Hello world"; let index; for(index in arr) { console.log("arr[" + index + "] = " + arr[index]); }
Le résultat en cours d'exécution est :
arr[0] = 1 arr[1] = 2 arr[2] = 3 arr[name] = Hello world arr[fatherName] = Father
En écrivant ceci, nous pouvons constater que for-in ne convient pas pour parcourir des éléments dans un tableau, il est plus adapté pour parcourir des attributs dans des objets, ceci est aussi l'intention originale pour laquelle il a été créé. Il existe une exception : les tableaux clairsemés. Prenons l'exemple suivant :
let key; const arr = []; arr[0] = "a"; arr[100] = "b"; arr[10000] = "c"; for(key in arr) { if(arr.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294 ) { console.log(arr[key]); } }
for-in 只会遍历存在的实体,上面的例子中, for-in 遍历了3次(遍历属性分别为”0″、 “100″、 “10000″的元素,普通 for 循环则会遍历 10001 次)。所以,只要处理得当, for-in 在遍历 Array 中元素也能发挥巨大作用。
为了避免重复劳动,我们可以包装一下上面的代码:
function arrayHasOwnIndex(array, prop) { return array.hasOwnProperty(prop) && /^0$|^[1-9]\d*$/.test(prop) && prop <= 4294967294; // 2^32 - 2 }
使用示例如下:
for (let key in arr) { if (arrayHasOwnIndex(arr, key)) { console.log(arr[key]); } }
for-in 性能
正如上面所说,每次迭代操作会同时搜索实例或者原型属性, for-in 循环的每次迭代都会产生更多开销,因此要比其他循环类型慢,一般速度为其他类型循环的 1/7。因此,除非明确需要迭代一个属性数量未知的对象,否则应避免使用 for-in 循环。如果需要遍历一个数量有限的已知属性列表,使用其他循环会更快,比如下面的例子:
const obj = { "prop1": "value1", "prop2": "value2" }; const props = ["prop1", "prop2"]; for(let i = 0; i < props.length; i++) { console.log(obj[props[i]]); }
上面代码中,将对象的属性都存入一个数组中,相对于 for-in 查找每一个属性,该代码只关注给定的属性,节省了循环的开销和时间。
在 ES5 中,引入了新的循环,即 forEach 循环。
const arr = [1, 2, 3]; arr.forEach((data) => { console.log(data); });
运行结果:
1 2 3
forEach 方法为数组中含有有效值的每一项执行一次 callback 函数,那些已删除(使用 delete 方法等情况)或者从未赋值的项将被跳过(不包括那些值为 undefined 或 null 的项)。 callback 函数会被依次传入三个参数:
需要注意的是,forEach 遍历的范围在第一次调用 callback 前就会确定。调用forEach 后添加到数组中的项不会被 callback 访问到。如果已经存在的值被改变,则传递给 callback 的值是 forEach 遍历到他们那一刻的值。已删除的项不会被遍历到。
const arr = []; arr[0] = "a"; arr[3] = "b"; arr[10] = "c"; arr.name = "Hello world"; arr.forEach((data, index, array) => { console.log(data, index, array); });
运行结果:
a 0 ["a", 3: "b", 10: "c", name: "Hello world"] b 3 ["a", 3: "b", 10: "c", name: "Hello world"] c 10 ["a", 3: "b", 10: "c", name: "Hello world"]
这里的 index 是 Number 类型,并且也不会像 for-in 一样遍历原型链上的属性。
所以,使用 forEach 时,我们不需要专门地声明 index 和遍历的元素,因为这些都作为回调函数的参数。
另外,forEach 将会遍历数组中的所有元素,但是 ES5 定义了一些其他有用的方法,下面是一部分:
forEach 性能
大家可以看 jsPerf ,在不同浏览器下测试的结果都是 forEach 的速度不如 for。如果大家把测试代码放在控制台的话,可能会得到不一样的结果,主要原因是控制台的执行环境与真实的代码执行环境有所区别。
先来看个例子:
const arr = ['a', 'b', 'c']; for(let data of arr) { console.log(data); }
运行结果是:
a b c
为什么要引进 for-of?
要回答这个问题,我们先来看看ES6之前的 3 种 for 循环有什么缺陷:
所以,鉴于以上种种缺陷,我们需要改进原先的 for 循环。但 ES6 不会破坏你已经写好的 JS 代码。目前,成千上万的 Web 网站依赖 for-in 循环,其中一些网站甚至将其用于数组遍历。如果想通过修正 for-in 循环增加数组遍历支持会让这一切变得更加混乱,因此,标准委员会在 ES6 中增加了一种新的循环语法来解决目前的问题,即 for-of 。
那 for-of 到底可以干什么呢?
总结一下,for-of 循环有以下几个特征:
但需要注意的是,for-of循环不支持普通对象,但如果你想迭代一个对象的属性,你可以用
for-in 循环(这也是它的本职工作)。
最后要说的是,ES6 引进的另一个方式也能实现遍历数组的值,那就是 Iterator。上个例子:
const arr = ['a', 'b', 'c']; const iter = arr[Symbol.iterator](); iter.next() // { value: 'a', done: false } iter.next() // { value: 'b', done: false } iter.next() // { value: 'c', done: false } iter.next() // { value: undefined, done: true }
前面的不多说,重点描述for-of
for-of循环不仅支持数组,还支持大多数类数组对象,例如DOM NodeList对象。
for-of循环也支持字符串遍历,它将字符串视为一系列的Unicode字符来进行遍历:
window.onload=function(){ const arr = [55,00, 11, 22]; arr.name = "hello"; // Array.prototype.FatherName = 'FatherName'; /*for(let key in arr){ console.log('key='+key+',key.value='+arr[key]); }*/ /* arr.forEach((data) => {console.log(data);});*/ /* arr.forEach((data,index,arr) => {console.log(data+','+index+','+arr);});*/ /*for(let key of arr){ console.log(key); }*/ var string1 = 'abcdefghijklmn'; var string2 = 'opqrstuvwxyc'; const stringArr = [string1,string2]; for(let key of stringArr){ console.log(key); } for(let key of string1){ console.log(key); } }
结果:
现在,只需记住:
for-in循环用来遍历对象属性。
for-of循环用来遍历数据—例如数组中的值。
它同样支持Map和Set对象遍历。
Map和Set对象是ES6中新增的类型。ES6中的Map和Set和java中并无太大出入。
Set
和Map
类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在Set
中,没有重复的key。
要创建一个Set
,需要提供一个Array
作为输入,或者直接创建一个空Set
:
var s1 = new Set(); // 空Set var s2 = new Set([1, 2, 3]); // 含1, 2, 3
重复元素在Set中自动被过滤:
var s = new Set([1, 2, 3, 3, '3']); console.log(s); // Set {1, 2, 3, "3"}
通过add(key)
方法可以添加元素到Set
中,可以重复添加,但不会有效果:
var s = new Set([1, 2, 3]); s.add(4); s; // Set {1, 2, 3, 4} s.add(4); s; // Set {1, 2, 3, 4}
通过delete(key)
方法可以删除元素:
var s = new Set([1, 2, 3]); s; // Set {1, 2, 3} s.delete(3); s; // Set {1, 2}
Set对象可以自动排除重复项
var string1 = 'abcdefghijklmn'; var string2 = 'opqrstuvwxyc'; var string3 = 'opqrstuvwxyc'; var string4 = 'opqrstuvwxyz'; const stringArr = [string1,string2,string3,string4]; var newSet = new Set(stringArr); for(let key of newSet){ console.log(key); }
结果:
Map对象稍有不同:内含的数据由键值对组成,所以你需要使用解构(destructuring)来将键值对拆解为两个独立的变量:
for (var [key, value] of phoneBookMap) { console.log(key + "'s phone number is: " + value); }
示例
var m = new Map([[1, 'Michael'], [2, 'Bob'], [3, 'Tracy']]); var map = new Map([['1','Jckey'],['2','Mike'],['3','zhengxin']]); map.set('4','Adam');//添加key-value map.set('5','Tom'); map.set('6','Jerry'); console.log(map.get('6')); map.delete('6'); console.log(map.get('6')); for(var [key,value] of map) { console.log('key='+key+' , value='+value); }
结果:
【相关推荐:javascript视频教程、编程视频】
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!