Maison > Article > interface Web > 10 bugs JavaScript courants et comment les corriger
La conception du langage JavaScript est trop flexible, il faut donc faire attention à l'utiliser et tomber dans les gouffres. La conception du langage JavaScript est trop flexible, et il faut faire attention à l'utiliser et tomber dans les gouffres. . Cet article partage avec vous 10 BUG JavaScript courants et comment les corriger. Aujourd’hui, près de 100 % des sites Web utilisent JavaScript. JavaScript semble être un langage très simple, mais ce n'est pas le cas. Il contient de nombreux détails sur lesquels il est facile de se tromper, ce qui peut entraîner des bugs si vous n'y prêtez pas attention.
Dans les fermetures ou les rappels, il est facile de se tromper sur la portée du mot-clé this
. Par exemple :
Game.prototype.restart = function () { this.clearLocalStorage(); this.timer = setTimeout(function() { this.clearBoard(); // 此处this指的是? }, 0); };
Si vous exécutez le code ci-dessus, nous verrons l'erreur :
Uncaught TypeError: undefined is not a function
La raison de l'erreur est : lorsque vous appelez la fonction setTimeout
, vous en fait L'appel est window.setTimeout()
. La fonction anonyme passée dans setTimeout
est dans l'environnement objet de window
, donc this
pointe vers window
, mais window
n'a pas de méthode clearBoard
.
Comment le résoudre ? Définissez une nouvelle référence de variable pour pointer vers le Game
de l'objet this
, et vous pourrez ensuite l'utiliser.
Game.prototype.restart = function () { this.clearLocalStorage(); var self = this; // 将this指向的对象绑定到self this.timer = setTimeout(function(){ self.clearBoard(); }, 0); };
Ou utilisez la fonction 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的引用正确 };
dans la plupart des langages de programmation Dans , chaque bloc fonction a un nouvelle portée indépendante, mais en JavaScript, ce n'est pas le cas. Par exemple :
for (var i = 0; i < 10; i++) { /* ... */ } console.log(i); // 会输出什么呢?
Habituellement, dans ce cas, appeler console.log()
affichera undefined
ou signalera une erreur. Cependant, 10
sera affiché ici. En JavaScript, même si la boucle for est terminée, la variable i
existe toujours et la dernière valeur est enregistrée. Certains développeurs l’oublient, ce qui entraîne de nombreux bugs. Nous pouvons utiliser let
au lieu de for
pour éviter ce problème.
Vous devez surveiller l'utilisation de la mémoire car les fuites sont difficiles à éviter. Des fuites de mémoire peuvent survenir en raison de références à des objets inexistants ou de références circulaires.
Comment éviter : Concentrez-vous sur l'accessibilité de l'objet.
Objets accessibles :
Objets accessibles depuis n'importe où dans la pile d'appels existante
Objet global
Lorsqu'un objet est accessible via une référence, il sera enregistré en mémoire. Le garbage collector du navigateur récupérera uniquement les objets inaccessibles.
JavaScript convertit automatiquement tous les types de variables dans les environnements booléens en types booléens, mais cela peut entraîner des bugs. Exemple :
// 所有都是true console.log(false == '0'); console.log(null == undefined); console.log(" \t\r\n" == 0); console.log('' == 0); // 注意:下面两个也是 if ({}) // … if ([]) // …
{}
et []
sont tous deux des objets, et ils seront convertis en vrai. Afin d'éviter les bugs, il est recommandé d'utiliser ===
et !==
à des fins de comparaison, car la conversion de type ne sera pas effectuée implicitement.
En JavaScript, vous pouvez facilement utiliser le DOM (ajouter, modifier et supprimer), mais les développeurs le font souvent de manière très inefficace. Cela peut entraîner des bugs car ces opérations sont très gourmandes en calcul. Pour résoudre ce problème, il est recommandé d'utiliser Document Fragment si vous devez exploiter plusieurs éléments DOM.
Publicité : Il n'y a vraiment aucun bug dans votre code en ligne ? Bienvenue à utiliser Fundebug gratuitement ! Nous pouvons vous aider à trouver les BUG dès que possible
Exemple :
var elements = document.getElementsByTagName('input'); var n = elements.length; // 假设我们有10个元素 for (var i = 0; i < n; i++) { elements[i].onclick = function() { console.log("元素编号#" + i); }; }
Si nous avons 10 éléments, alors cliquer sur n'importe quel élément affichera « Élément numéro #10 » ! Parce que lorsque onclick
est appelé, la boucle for est terminée, donc tous les i valent 10.
Solution :
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); }
makeHandler
est appelé immédiatement lorsque la boucle for est exécutée, obtient la valeur actuelle i+1
et la stocke dans la variable num
. makeHandler
Renvoie une fonction utilisant la variable num
liée à l'événement click de l'élément.
Si les développeurs ne comprennent pas correctement les principes de l'héritage, ils peuvent écrire du code bogué :
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'
Mais, si nous faisons le suivant :
delete secondObj.name;
Ensuite :
console.log(secondObj.name); // -> 输出'undefined'
Et ce que nous voulons en fait, c'est imprimer le nom par défaut.
BaseObject = function (name) { if(typeof name !== "undefined") { this.name = name; } }; BaseObject.prototype.name = 'default';
Chaque BaseObject
hérite de l'attribut name
et la valeur par défaut est default
. À ce stade, si l'attribut secondObj
de name
est supprimé, la recherche dans la chaîne de prototypes renverra la valeur par défaut correcte.
var thirdObj = new BaseObject('unique'); console.log(thirdObj.name); // -> 输出'unique' delete thirdObj.name; console.log(thirdObj.name); // -> 输出'default'
Implémentons un constructeur simple pour créer des objets :
var MyObject = function() {} MyObject.prototype.whoAmI = function() { console.log(this === window ? "window" : "MyObj"); }; var obj = new MyObject();
Pour faciliter l'utilisation, nous définissons la variable whoAmI
pour référencer obj.whoAmI
:
var whoAmI = obj.whoAmI;
Imprimez-le :
console.log(whoAmI);
La console affichera :
function () { console.log(this === window ? "window" : "MyObj"); }
Maintenant, comparons la différence entre les deux appels :
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的使用方法介绍
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!