Heim > Web-Frontend > js-Tutorial > Hauptteil

Sollten Sie sich aus Leistungsgründen für die Schleifendurchquerung entscheiden?

hzc
Freigeben: 2020-06-16 10:05:41
nach vorne
2021 Leute haben es durchsucht

Die 5 Kräfte, die auf dem Schlachtfeld ankommen

Selbstvorstellungssitzung


für

Ich bin the Traverse World Der erste Prinz, der erscheint, jeder hier muss mich Opa nennen. Ich kann die meisten Anforderungen des Entwicklers erfüllen.

sind 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(&#39;.article > p&#39;);
for(let i = 0;i<articleParagraphs.length;i++){
    articleParagraphs[i].classList.add("paragraph");
    // 给class名为“article”节点下的 p 标签添加一个名为“paragraph” class属性。
}
Nach dem Login kopieren

forEach

Ich bin die ES5-Version freigegeben. Die Rückruffunktion wird einmal für jedes Element im Array ausgeführt, das einen gültigen Wert in aufsteigender Reihenfolge enthält. Die Elemente, die gelöscht oder nicht initialisiert wurden, werden übersprungen (z. B. bei Arrays mit geringer Dichte). Ich bin eine erweiterte Version der for-Schleife.

// 遍历数组
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])     // 对象的键对应的值
})
Nach dem Login kopieren

map

Ich bin auch in der ES5-Version verfügbar. Das Ergebnis des neuen Arrays ist der Rückgabewert, nachdem die bereitgestellte Funktion einmal für jedes Element aufgerufen wurde Original-Array.

let arr = [1,2,3,4,5];
let res = arr.map(i => i * i);

console.log(res) // logs [1, 4, 9, 16, 25]
Nach dem Login kopieren

für...in Enumeration

Ich habe die ES5-Version veröffentlicht. Durchläuft die aufzählbaren Eigenschaften eines Objekts mit Ausnahme von Symbol in beliebiger Reihenfolge.

// 遍历对象
let profile = {name:"April",nickname:"二十七刻",country:"China"};
for(let i in profile){
    let item = profile[i];
    console.log(item)   // 对象的键值
    console.log(i)      // 对象的键对应的值

// 遍历数组
let arr = [&#39;a&#39;,&#39;b&#39;,&#39;c&#39;];
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)      // 索引 字符串的下标
}
Nach dem Login kopieren

für...der Iteration

Ich habe die ES6-Version veröffentlicht. Erstellen Sie eine Iterationsschleife über ein iterierbares Objekt (einschließlich Array, Map, Set, String, TypedArray, Argumentobjekte usw.), rufen Sie einen benutzerdefinierten Iterations-Hook auf und führen Sie Anweisungen für jeden einzelnen Eigenschaftswert aus.

// 迭代数组数组
let arr = [&#39;a&#39;,&#39;b&#39;,&#39;c&#39;];
for(let item of arr){
    console.log(item)     
}
// logs &#39;a&#39;
// logs &#39;b&#39;
// logs &#39;c&#39;

// 迭代字符串
let str = "abc";
for (let value of str) {
    console.log(value);
}
// logs &#39;a&#39;
// logs &#39;b&#39;
// logs &#39;c&#39;

// 迭代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(&#39;.article > p&#39;);
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
Nach dem Login kopieren

Nach der ersten Runde der Selbstvorstellung und Demonstration der Fähigkeiten haben wir gelernt:

  • Die for-Anweisung ist die primitivste Schleifenanweisung. Definieren Sie eine Variable i (numerischer Typ, der den Index des Arrays darstellt) und führen Sie eine zyklische Akkumulation von i gemäß bestimmten Bedingungen durch. Die Bedingung ist normalerweise die Länge des Schleifenobjekts. Wenn die Länge überschritten wird, stoppt die Schleife. Da das Objekt die Länge nicht bestimmen kann, wird es mit Object.keys() verwendet.

  • Vorgeschlagen von forEach ES5. Obwohl es sich um eine erweiterte Version der for-Anweisung handelt, kann man feststellen, dass sie viel einfacher zu schreiben ist als die for-Anweisung. Aber es ist im Wesentlichen eine Schleife von Arrays. forEach führt die Callback-Funktion einmal für jedes Array-Element aus. Das ist das Array, in dem es aufgerufen wird, sodass das ursprüngliche Array nicht geändert wird. Der Rückgabewert ist undefiniert.

  • von ES5 vorgeschlagene Karte. Rufen Sie die Rückruffunktion nacheinander einmal für jedes Element im ursprünglichen Array auf. Erzeugt ein neues Array, ohne das ursprüngliche Array zu ändern, von dem es aufgerufen wurde. Der Rückgabewert ist das neue Array.

  • für...in ES5 vorgeschlagen. Durchlaufen Sie die aufzählbaren Eigenschaften des Objekts, einschließlich der Eigenschaften des Prototypobjekts, und durchlaufen Sie sie in beliebiger Reihenfolge, dh die Reihenfolge ist nicht festgelegt. Beim Durchlaufen des Arrays wird der Index des Arrays als Schlüsselwert verwendet. Zu diesem Zeitpunkt ist i ein Zeichenfolgentyp. Es ist für die Iteration über Objekteigenschaften konzipiert und wird nicht für die Verwendung mit Arrays empfohlen.

  • für...von ES6 vorgeschlagen. Iterieren Sie nur über die Daten des iterierbaren Objekts.

Fähigkeitsidentifizierung


Als Programmierer reicht es nicht aus, sie nur zu kennen. Es ist notwendig, sie tatsächlich zu identifizieren Entwicklung. Die Vor- und Nachteile von. Nutzen Sie sie entsprechend den örtlichen Gegebenheiten und maximieren Sie ihre Stärken und vermeiden Sie ihre Schwächen. Die Fähigkeit besteht darin, die Gesamtleistung des Programms zu verbessern.

Über das Herausspringen aus dem Schleifenkörper

Brechen Sie aus dem Schleifenkörper aus, wenn bestimmte Bedingungen in der Schleife erfüllt sind, oder überspringen Sie Daten, die die Bedingungen nicht erfüllen, und fahren Sie mit der Schleife anderer Daten fort. Es handelt sich um eine Anforderung, die häufig anzutreffen ist. Häufig verwendete Anweisungen sind „break“ und „continue“.

Lassen Sie uns kurz über den Unterschied zwischen den beiden sprechen, nur zur Überprüfung.

  • Die break-Anweisung dient dazu, aus der aktuellen Schleife zu springen und die Anweisung nach der aktuellen Schleife auszuführen; die

  • continue-Anweisung dient zum Beenden Die aktuelle Schleife und die Ausführung fortsetzen.

Hinweis: forEach und map unterstützen das Herausspringen aus dem Schleifenkörper nicht, die anderen drei Methoden jedoch schon.

Prinzip: Wenn Sie sich das Implementierungsprinzip von forEach ansehen, werden Sie dieses Problem verstehen.

Array.prototype.forEach(callbackfn [,thisArg]{
    
}
Nach dem Login kopieren

Die übergebene Funktion ist hier die Rückruffunktion. Es ist definitiv illegal, break in einer Callback-Funktion zu verwenden, da break nur zum Ausbrechen einer Schleife verwendet werden kann und die Callback-Funktion nicht der Schleifenkörper ist.

Die Verwendung von return in der Rückruffunktion gibt das Ergebnis nur an die übergeordnete Funktion, also diese for-Schleife, zurück und beendet die for-Schleife nicht, sodass return ebenfalls ungültig ist.

map() funktioniert auf die gleiche Weise.

map()-Kettenaufruf

Die Methode map() kann in einer Kette aufgerufen werden, was bedeutet, dass sie bequem in Verbindung mit anderen Methoden verwendet werden kann. Zum Beispiel: Reduce(), Sort(), Filter() usw. Andere Methoden können dies jedoch nicht. Der Rückgabewert von forEach() ist undefiniert und kann daher nicht in einer Kette aufgerufen werden.

// 将元素乘以本身,再进行求和。
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"
Nach dem Login kopieren

for...in durchläuft die Eigenschaften des Prototypobjekts

Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};
var arr = [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;];
arr.foo = &#39;hello
for (var i in arr) {
    console.log(i);
}
// logs
// 0
// 1
// 2
// foo
// arrCustom
// objCustom
Nach dem Login kopieren

In der tatsächlichen Entwicklung benötigen wir jedoch nicht die Eigenschaften des Prototypobjekts. In diesem Fall können wir die Methode hasOwnProperty() verwenden, die einen booleschen Wert zurückgibt, der angibt, ob das Objekt die angegebene Eigenschaft in seinen eigenen Eigenschaften hat (d. h. ob der angegebene Schlüssel vorhanden ist). Wie folgt:

Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};
var arr = [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;];
arr.foo = &#39;hello
for (var i in arr) {
    if (arr.hasOwnProperty(i)) {
        console.log(i);
    }
}
// logs
// 0
// 1
// 2
// foo

// 可见数组本身的属性还是无法摆脱。此时建议使用 forEach
Nach dem Login kopieren

对于纯对象的遍历,选择for..in枚举更方便;对于数组遍历,如果不需要知道索引for..of迭代更合适,因为还可以中断;如果需要知道索引,则forEach()更合适;对于其他字符串,类数组,类型数组的迭代,for..of更占上风更胜一筹。但是注意低版本浏览器的是配性。

性能

有兴趣的读者可以找一组数据自行测试,文章就直接给出结果了,并做相应的解释。

for > for-of > forEach  > map > for-in
Nach dem Login kopieren
  • 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教程

Das obige ist der detaillierte Inhalt vonSollten Sie sich aus Leistungsgründen für die Schleifendurchquerung entscheiden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
js
Quelle:juejin.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!