Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Code-Erklärungen zu den drei häufigsten Problemen in JavaScript

Detaillierte Code-Erklärungen zu den drei häufigsten Problemen in JavaScript

黄舟
黄舟Original
2017-03-23 14:49:031098Durchsuche

JavaScript ist die offizielle Sprache aller modernen Browser. Daher treten JavaScript-Probleme auf In Interviews mit verschiedenen Entwicklern teilen wir Ihnen hauptsächlich die drei häufigsten Interviewfragen mit.

Vorwort

In diesem Artikel geht es nicht um die neuesten JavaScript-Bibliotheken, alltägliche Entwicklungspraktiken oder neue ES6-Funktionen

, wie es oft der Fall ist, wenn es um JavaScript geht Diese Fragen wurden mir selbst gestellt, und meine Freunde haben mir gesagt, dass sie auch gestellt wurden.

Natürlich sollten Sie diese 3 Fragen nicht nur vor dem JavaScript-Interview lernen – es gibt viele Möglichkeiten, sich besser vorzubereiten für Ihr bevorstehendes Vorstellungsgespräch – aber hier sind 3 Fragen, die Ihr Interviewer stellen könnte, um Ihr Verständnis der JavaScript-Sprache und die Beherrschung des DOM zu ermitteln.

Beginnen wir mit der Verwendung von nativem JavaScript unten, da Ihr Interviewer normalerweise sehen möchte, was Sie ohne die Hilfe einer Drittanbieterbibliothek wie

jQuery

tun. Wie man JavaScript und DOM versteht >Frage Nr. 1: Ereignisdelegation

Hinweis: Wird auch als Ereignisdelegation, Zeit-Proxy usw. bezeichnet. ;Manchmal beim Erstellen einer Anwendung Sie müssen Ereignis-Listener an Schaltflächen, Text oder Bilder auf der Seite binden, um bestimmte Aktionen auszuführen, wenn der Benutzer mit dem Element interagiert. >Wenn wir eine einfache Aufgabenliste als Beispiel nehmen, kann dies der Interviewer sein Sagen Sie, dass eine Aktion ausgeführt wird, wenn der Benutzer auf eines der Listenelemente klickt. Sie möchten, dass Sie JavaScript verwenden, um diese Funktion zu implementieren:

Möglicherweise möchten Sie einen Ereignis-Listener wie folgt an das Element binden:

Dies erledigt zwar die Aufgabe, das Problem besteht jedoch darin, dass Sie den Ereignis-Listener an jedes Element binden Listen Sie die Elemente einzeln auf, also 4 Elemente. Das ist keine große Sache, aber wenn jemand etwas auf seiner To-Do-Liste hat, was ist, wenn Sie 10.000 Elemente hinzufügen (sie haben möglicherweise viel zu tun)? Dann erstellt Ihre Funktion 10.000 unabhängige Ereignis-Listener und bindet sie Ereignis-Listener für das DOM.

Bei Interviews ist es eine gute Idee, den Interviewer zunächst zu fragen, wie viele Dinge der Benutzer eingeben kann in Ordnung, wenn es nie mehr als 10 beträgt. Wenn die Anzahl der Elemente, die der Benutzer eingeben kann, jedoch unbegrenzt ist, sollten Sie eine effizientere Lösung verwenden.

Wenn Ihre Anwendung möglicherweise Hunderte von Ereignis-Listenern enthält, besteht eine effizientere Lösung darin, tatsächlich einen Ereignis-Listener an den gesamten Container zu binden und dann auf jeden einzelnen zu zugreifen, wenn tatsächlich auf ein bestimmtes Element geklickt wird. Dies wird als Ereignisdelegation bezeichnet und macht die Bindung von Ereignishandlern individuell für jedes Element effizienter.
<ul id="todo-app">
 <li class="item">Walk the dog</li>
 <li class="item">Pay bills</li>
 <li class="item">Make dinner</li>
 <li class="item">Code for one hour</li>
</ul>

Code mit Ereignisdelegierung:

document.addEventListener(&#39;DOMContentLoaded&#39;, function() {
 
 let app = document.getElementById(&#39;todo-app&#39;);
 let items = app.getElementsByClassName(&#39;item&#39;);
 
 // 将事件侦听器绑定到每个列表项
 for (let item of items) {
 item.addEventListener(&#39;click&#39;, function() {
 alert(&#39;you clicked on item: &#39; + item.innerHTML);
 });
 }
 
});

Problem Nr. 2: Verwendung von Abschlüssen innerhalb von Schleifen

Abschlüsse kommen in Vorstellungsgesprächen oft vor, damit der Interviewer einschätzen kann, wie vertraut Sie mit der Sprache sind und ob Sie wissen, wann Abschlüsse zu verwenden sind.

Das Wesentliche an einem Abschluss ist, dass eine interne Funktion auf Variablen außerhalb ihres Gültigkeitsbereichs zugreift. Abschlüsse können verwendet werden, um Dinge wie private Variablen zu implementieren und Factory-Funktionen zu erstellen. Eine häufige Frage in Vorstellungsgesprächen zur Verwendung von Abschlüssen lautet wie folgt:

document.addEventListener(&#39;DOMContentLoaded&#39;, function() {
 
 let app = document.getElementById(&#39;todo-app&#39;);
 
 // 事件侦听器绑定到整个容器上
 app.addEventListener(&#39;click&#39;, function(e) {
 if (e.target && e.target.nodeName === &#39;LI&#39;) {
 let item = e.target;
 alert(&#39;you clicked on item: &#39; + item.innerHTML);
 }
 });
 
});
Schreiben Sie eine Funktion, die eine Liste von Ganzzahlen durchläuft und den Index jedes Elements nach einer Verzögerung von 3 Sekunden ausgibt.

Die häufigste (aber falsche) Art und Weise, wie ich dieses Problem sehe, ist eine Implementierung wie diese:

Wenn Sie den obigen Code ausführen, wird nach einer 3 Sekundenverzögerung Sie werden sehen, dass die gedruckte Ausgabe tatsächlich jedes Mal 4 ist, statt der erwarteten 0, 1, 2, 3.

Um richtig zu verstehen, warum dies geschieht, ist es nützlich, in JavaScript zu arbeiten, was der Interviewer eigentlich beabsichtigt hat. Der Grund dafür ist, dass die setTimeout-Funktion eine Funktion erstellt, die auf ihren äußeren Bereich zugreifen kann (das heißt, was wir oft als Abschluss bezeichnen), und jede Schleife den Index i enthält.

Nach 3 Sekunden wird die Funktion ausgeführt und gibt den Wert von i aus, der am Ende der Schleife 4 ist, da sein Schleifenzyklus 0,1,2,3,4 durchläuft und die Schleife schließlich bei endet 4 .

Es gibt tatsächlich mehrere richtige Möglichkeiten, dieses Problem zu schreiben:

const arr = [10, 12, 15, 21];
for (var i = 0; i < arr.length; i++) {
 setTimeout(function() {
 console.log(&#39;The index of this number is: &#39; + i);
 }, 3000);
}

Frage Nr. 3: Funktion Entprellen


有一些浏览器事件可以在很短的时间内快速启动多次,例如调整窗口大小或向下滚动页面。例如,如果将事件侦听器绑定到窗口滚动事件上,并且用户继续非常快速地向下滚动页面,你的事件可能会在3秒的范围内被触发数千次。这可能会导致一些严重的性能问题。

如果你在面试中讨论构建应用程序和事件,如滚动,窗口调整大小,或键盘按下的事件时,请务必提及 函数防抖动(Debouncing) 和/或 函数节流(Throttling)来提升页面速度和性能。一个真实的案例,来自 guest post on css-tricks:

在2011年,一个问题在Twitter上被提出:当你滚动Twitter feed时,它会会变得非常慢甚至未响应。John Resig 就这个问题发布了一篇博文,它解释了直接绑定函数到scroll事件上是多么糟糕的事。

函数防抖动(Debouncing) 是解决这个问题的一种方式,通过限制需要经过的时间,直到再次调用函数。一个正确实现函数防抖的方法是:把多个函数放在一个函数里调用,隔一定时间执行一次。这里有一个使用原生JavaScript实现的例子,用到了作用域、闭包、this和定时事件:

// debounce函数用来包裹我们的事件
function debounce(fn, delay) {
 // 持久化一个定时器 timer
 let timer = null;
 // 闭包函数可以访问 timer
 return function() {
 // 通过 &#39;this&#39; 和 &#39;arguments&#39;
 // 获得函数的作用域和参数
 let context = this;
 let args = arguments;
 // 如果事件被触发,清除 timer 并重新开始计时
 clearTimeout(timer);
 timer = setTimeout(function() {
 fn.apply(context, args);
 }, delay);
 }
}

当这个函数绑定在一个事件上,只有经过一段指定的时间后才会被调用。

你可以像这样去使用这个函数:

// 当用户滚动时函数会被调用
function foo() {
 console.log(&#39;You are scrolling!&#39;);
}
 
// 在事件触发的两秒后,我们包裹在debounce中的函数才会被触发
let elem = document.getElementById(&#39;container&#39;);
elem.addEventListener(&#39;scroll&#39;, debounce(foo, 2000));

函数节流是另一个类似函数防抖的技巧,除了使用等待一段时间再调用函数的方法,函数节流还限制固定时间内只能调用一次。所以一个事件如果在100毫秒内发生10次,函数节流会每2秒调用一次函数,而不是100毫秒内全部调用。

总结

Das obige ist der detaillierte Inhalt vonDetaillierte Code-Erklärungen zu den drei häufigsten Problemen in JavaScript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
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