Heim >Web-Frontend >js-Tutorial >10 häufige JavaScript-Fehler und wie man sie behebt
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.
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); };
Wenn Sie den obigen Code ausführen, wird ein Fehler angezeigt:
Uncaught TypeError: undefined is not a function
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); };
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的引用正确 };
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); // 会输出什么呢?
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.
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.
JavaScript konvertiert automatisch alle Variablentypen in booleschen Umgebungen, dies kann jedoch zu Fehlern führen. Beispiel:
// 所有都是true console.log(false == '0'); console.log(null == undefined); console.log(" \t\r\n" == 0); console.log('' == 0); // 注意:下面两个也是 if ({}) // … if ([]) // …
{}
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.
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!
Wenn wir 10 Elemente haben, wird beim Klicken auf ein beliebiges Element „Elementnummer #10“ angezeigt! Denn wenn
var elements = document.getElementsByTagName('input'); var n = elements.length; // 假设我们有10个元素 for (var i = 0; i < n; i++) { elements[i].onclick = function() { console.log("元素编号#" + i); }; }aufgerufen wird, ist die for-Schleife beendet, sodass alle i-Werte 10 sind.
onclick
Lösung:
var elements = document.getElementsByTagName('input'); 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); }wird sofort aufgerufen, wenn die for-Schleife ausgeführt wird, erhält den aktuellen Wert
und speichert ihn in der Variablen makeHandler
. i+1
Gibt eine Funktion zurück, die die Variable num
verwendet, die an das Klickereignis des Elements gebunden ist. makeHandler
num
7. Falsche Vererbung durch Prototypen
BaseObject = function(name) { if(typeof name !== "undefined") { this.name = name; } else { this.name = 'default' } }; var firstObj = new BaseObject(); var secondObj = new BaseObject('unique'); console.log(firstObj.name); // -> 输出'default' console.log(secondObj.name); // -> 输出'unique'Dann:
delete secondObj.name;Und was wir eigentlich wollen, ist, den Standardnamen zu drucken.
console.log(secondObj.name); // -> 输出'undefined'Jedes
BaseObject = function (name) { if(typeof name !== "undefined") { this.name = name; } }; BaseObject.prototype.name = 'default';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. secondObj
name
var thirdObj = new BaseObject('unique'); console.log(thirdObj.name); // -> 输出'unique' delete thirdObj.name; console.log(thirdObj.name); // -> 输出'default'
var MyObject = function() {} MyObject.prototype.whoAmI = function() { console.log(this === window ? "window" : "MyObj"); }; var obj = new MyObject();zur Referenz
: whoAmI
obj.whoAmI
var whoAmI = obj.whoAmI;Die Konsole gibt Folgendes aus:
console.log(whoAmI);Jetzt vergleichen wir die Unterschied zwischen den beiden Aufrufen:
function () { console.log(this === window ? "window" : "MyObj"); }
obj.whoAmI(); // 输出"MyObj" (和期望一致) whoAmI(); // 输出"window" (竟然输出了window)
当我们把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"
如果你将一个字符串作为setTimeout/setTimeInterval,它会被传给函数构造函数并构建一个新的函数。该操作流程很慢而且低效,并导致bug出现。
var hello = function(){ console.log("hello, fundebug !"); } setTimeout("hello", 1000);
一个好的替代方法就是传入函数作为参数:
setInterval(logTime, 1000); // 将logTime函数传入 setTimeout(function() { // 传入一个匿名函数 logMessage(msgValue); }, 1000);
使用strict model会增加很多限制条件来加强安全和防止某些错误的出现,如果不使用strict mode
,你就相当于少了一个得力的助手帮你避免错误:
更加容易debug
避免不小心定义了不该定义的全局变量
避免this隐式转换
避免属性名字或则参数值的重复使用
eval()更加安全
无效地使用delete会自动抛出错误
以上内容就是10个JavaScript常见BUG及修复方法,希望能帮助到大家。
相关推荐:
PHP中调试函数debug_backtrace的使用方法介绍
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!