Heim > Web-Frontend > js-Tutorial > Hauptteil

10 häufige JavaScript-Fehler und wie man sie behebt

小云云
Freigeben: 2017-12-06 15:51:42
Original
1434 Leute haben es durchsucht

Das Design der JavaScript-Sprache ist zu flexibel, daher muss man bei der Verwendung vorsichtig sein und in Schwierigkeiten geraten. In diesem Artikel erfahren Sie mehr über 10 häufige JavaScript-Fehler und wie Sie diese beheben können. Fast 100 % der Websites verwenden heutzutage JavaScript. JavaScript scheint eine sehr einfache Sprache zu sein, aber das ist nicht der Fall. Es enthält viele Details, die leicht falsch gemacht werden können, was zu Fehlern führen kann, wenn Sie nicht aufpassen.

1. Falscher Verweis darauf

Bei Abschlüssen oder Rückrufen kann es leicht passieren, dass der Umfang des Schlüsselworts this falsch ist. Zum Beispiel:

Game.prototype.restart = function () {
  this.clearLocalStorage();
  this.timer = setTimeout(function() {
    this.clearBoard();    // 此处this指的是?
  }, 0);
};
Nach dem Login kopieren

Wenn Sie den obigen Code ausführen, wird ein Fehler angezeigt:

Uncaught TypeError: undefined is not a function
Nach dem Login kopieren

Der Grund für den Fehler ist: Wenn Sie die Funktion setTimeout aufrufen, Sie tatsächlich Der Anruf ist window.setTimeout(). Die in setTimeout übergebene anonyme Funktion befindet sich in der Objektumgebung von window, daher zeigt this auf window, aber window verfügt nicht über eine clearBoard-Methode.

Wie kann man es lösen? Definieren Sie einen neuen Variablenverweis, der auf das Game des this-Objekts verweist, und Sie können ihn dann verwenden.

Game.prototype.restart = function () {
  this.clearLocalStorage();
  var self = this;   // 将this指向的对象绑定到self
  this.timer = setTimeout(function(){
    self.clearBoard();
  }, 0);
};
Nach dem Login kopieren

Oder verwenden Sie die Funktion bind():

Game.prototype.restart = function () {
  this.clearLocalStorage();
  this.timer = setTimeout(this.reset.bind(this), 0);  // bind to 'this'
};

Game.prototype.reset = function(){
    this.clearBoard();    // 此处this的引用正确
};
Nach dem Login kopieren

2. FEHLER im Zusammenhang mit dem Blockumfang

in den meisten Programmiersprachen. In hat jeder Funktionsblock eine unabhängiger neuer Bereich, aber in JavaScript ist dies nicht der Fall. Beispiel:

for (var i = 0; i < 10; i++) {
  /* ... */
}
console.log(i);  // 会输出什么呢?
Nach dem Login kopieren

Normalerweise wird in diesem Fall beim Aufruf von console.log() undefined ausgegeben oder ein Fehler gemeldet. Allerdings wird hier 10 ausgegeben. In JavaScript ist die Variable i auch dann noch vorhanden, wenn die for-Schleife beendet wurde, und der letzte Wert wird aufgezeichnet. Einige Entwickler vergessen dies, was zu vielen Fehlern führt. Wir können let anstelle von for verwenden, um dieses Problem zu vermeiden.

3. Speicherlecks

Sie müssen die Speichernutzung überwachen, da Lecks schwer zu vermeiden sind. Durch Verweise auf nicht vorhandene Objekte oder Zirkelverweise kann es zu Speicherverlusten kommen.

  • So vermeiden Sie: Konzentrieren Sie sich auf die Erreichbarkeit des Objekts.

  • Zugreifbare Objekte:

    • Objekte, auf die von überall im vorhandenen Aufrufstapel zugegriffen werden kann

    • Globales Objekt

Wenn auf ein Objekt über eine Referenz zugegriffen werden kann, wird es im Speicher gespeichert. Der Garbage Collector des Browsers fordert nur Objekte zurück, auf die nicht zugegriffen werden kann.

4. Verwirrte Gleichheitsbeurteilung

JavaScript konvertiert automatisch alle Variablentypen in booleschen Umgebungen, dies kann jedoch zu Fehlern führen. Beispiel:

// 所有都是true
console.log(false == &#39;0&#39;);
console.log(null == undefined);
console.log(" \t\r\n" == 0);
console.log(&#39;&#39; == 0);

// 注意:下面两个也是
if ({}) // …
if ([]) // …
Nach dem Login kopieren

{} und [] sind beide Objekte und werden in true konvertiert. Um Fehler zu vermeiden, wird empfohlen, zum Vergleich === und !== zu verwenden, da die Typkonvertierung nicht implizit durchgeführt wird.

5. Ineffiziente DOM-Operationen

In JavaScript können Sie das DOM problemlos bedienen (Hinzufügen, Ändern und Löschen), aber Entwickler tun dies oft sehr ineffizient. Dies kann zu Fehlern führen, da diese Vorgänge sehr rechenintensiv sind. Um dieses Problem zu lösen, wird empfohlen, Document Fragment zu verwenden, wenn Sie mehrere DOM-Elemente bedienen müssen.

Werbung: Ist wirklich kein Fehler in Ihrem Online-Code? Willkommen bei der kostenlosen Nutzung von Fundebug!

Falsche Definition der Funktion in for-Schleife

Wenn wir 10 Elemente haben, wird beim Klicken auf ein beliebiges Element „Elementnummer #10“ angezeigt! Denn wenn
var elements = document.getElementsByTagName(&#39;input&#39;);
var n = elements.length;    // 假设我们有10个元素
for (var i = 0; i < n; i++) {
    elements[i].onclick = function() {
        console.log("元素编号#" + i);
    };
}
Nach dem Login kopieren
aufgerufen wird, ist die for-Schleife beendet, sodass alle i-Werte 10 sind.

onclick Lösung:

var elements = document.getElementsByTagName(&#39;input&#39;);
var n = elements.length;    // 假设有10个元素
var makeHandler = function(num) {  // outer function
     return function() {   // inner function
         console.log("元素编号##" + num);
     };
};
for (var i = 0; i < n; i++) {
    elements[i].onclick = makeHandler(i+1);
}
Nach dem Login kopieren
wird sofort aufgerufen, wenn die for-Schleife ausgeführt wird, erhält den aktuellen Wert

und speichert ihn in der Variablen makeHandler. i+1Gibt eine Funktion zurück, die die Variable num verwendet, die an das Klickereignis des Elements gebunden ist. makeHandlernum7. Falsche Vererbung durch Prototypen

Wenn Entwickler die Prinzipien der Vererbung nicht richtig verstehen, schreiben sie möglicherweise fehlerhaften Code:

Aber wenn wir das tun Folgendes:
BaseObject = function(name) {
    if(typeof name !== "undefined") {
        this.name = name;
    } else {
        this.name = &#39;default&#39;
    }
};
var firstObj = new BaseObject();
var secondObj = new BaseObject(&#39;unique&#39;);

console.log(firstObj.name);  // -> 输出'default'
console.log(secondObj.name); // -> 输出'unique'
Nach dem Login kopieren

Dann:
delete secondObj.name;
Nach dem Login kopieren

Und was wir eigentlich wollen, ist, den Standardnamen zu drucken.
console.log(secondObj.name); // -> 输出'undefined'
Nach dem Login kopieren

Jedes
BaseObject = function (name) {
    if(typeof name !== "undefined") {
        this.name = name;
    }
};

BaseObject.prototype.name = 'default';
Nach dem Login kopieren
erbt das Attribut

und der Standardwert ist BaseObject. Wenn zu diesem Zeitpunkt das name-Attribut von default gelöscht wird, wird beim Durchsuchen der Prototypenkette der korrekte Standardwert zurückgegeben. secondObjname

8. Ungültige Referenzen in Instanzmethoden
var thirdObj = new BaseObject('unique');
console.log(thirdObj.name);  // -> 输出'unique'

delete thirdObj.name;
console.log(thirdObj.name);  // -> 输出'default'
Nach dem Login kopieren

Implementieren wir einen einfachen Konstruktor zum Erstellen von Objekten:

Zur Vereinfachung der Verwendung definieren wir die Variable
var MyObject = function() {}

MyObject.prototype.whoAmI = function() {
    console.log(this === window ? "window" : "MyObj");
};

var obj = new MyObject();
Nach dem Login kopieren
zur Referenz

: whoAmIobj.whoAmI

Drucken Sie es aus und sehen Sie:
var whoAmI = obj.whoAmI;
Nach dem Login kopieren

Die Konsole gibt Folgendes aus:
console.log(whoAmI);
Nach dem Login kopieren

Jetzt vergleichen wir die Unterschied zwischen den beiden Aufrufen:
function () {
    console.log(this === window ? "window" : "MyObj");
}
Nach dem Login kopieren
obj.whoAmI();  // 输出"MyObj" (和期望一致)
whoAmI();      // 输出"window" (竟然输出了window)
Nach dem Login kopieren

当我们把obj.whoAmI赋值给whoAmI的时候,这个新的变量whoAmI是定义在全局下,因此this指向全局的window,而不是MyObj。如果我们真的要获取对MyObj的函数的引用,需要在其作用域下。

var MyObject = function() {}

MyObject.prototype.whoAmI = function() {
    console.log(this === window ? "window" : "MyObj");
};

var obj = new MyObject();
obj.w = obj.whoAmI;   // 任然在obj的作用域

obj.whoAmI();  // 输出"MyObj"
obj.w();       // 输出"MyObj"
Nach dem Login kopieren

9. setTimeout/setInterval函数第一个参数误用字符串

如果你将一个字符串作为setTimeout/setTimeInterval,它会被传给函数构造函数并构建一个新的函数。该操作流程很慢而且低效,并导致bug出现。

var hello = function(){
  console.log("hello, fundebug !");
}
setTimeout("hello", 1000);
Nach dem Login kopieren

一个好的替代方法就是传入函数作为参数:

setInterval(logTime, 1000);   // 将logTime函数传入

setTimeout(function() {       // 传入一个匿名函数
    logMessage(msgValue);     
  }, 1000);
Nach dem Login kopieren

10. 未能成功使用strict mode

使用strict model会增加很多限制条件来加强安全和防止某些错误的出现,如果不使用strict mode,你就相当于少了一个得力的助手帮你避免错误:

  • 更加容易debug

  • 避免不小心定义了不该定义的全局变量

  • 避免this隐式转换

  • 避免属性名字或则参数值的重复使用

  • eval()更加安全

  • 无效地使用delete会自动抛出错误

以上内容就是10个JavaScript常见BUG及修复方法,希望能帮助到大家。

相关推荐:

PHP中调试函数debug_backtrace的使用方法介绍

JavaScript调试必备的5个debug技巧分享

JS中offsetWidth的bug及处理方法

Das obige ist der detaillierte Inhalt von10 häufige JavaScript-Fehler und wie man sie behebt. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.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