Home  >  Article  >  Web Front-end  >  10 common JavaScript bugs and how to fix them

10 common JavaScript bugs and how to fix them

小云云
小云云Original
2017-12-06 15:51:421422browse

The design of the JavaScript language is too flexible, so you have to be careful about falling into pits when using it. The design of the JavaScript language is too flexible, so you have to be careful about falling into pits when using it. This article shares with you 10 common JavaScript BUGs and how to fix them. Almost 100% of websites today use JavaScript. JavaScript seems to be a very simple language, but this is not the case. It has a lot of details that are easy to get wrong, which can lead to bugs if you don't pay attention.

1. Wrong reference to this

In closures or callbacks, the scope of the this keyword is easy to get wrong. For example:

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

If you execute the above code, we will see an error:

Uncaught TypeError: undefined is not a function

The reason for the error is: when you call the setTimeout function, you actually The call is window.setTimeout(). The anonymous function passed in setTimeout is in the object environment of window, so this points to window, but window does not have a clearBoard method.

How to solve it? Define a new variable reference that points to this of the Game object, and then you can use it.

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

Or use the bind() function:

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

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

2. BUGs related to block scope

In most cases In programming languages, each function block has an independent new scope, but not in JavaScript. For example:

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

Usually in this case, calling console.log() will output undefined or report an error. However, 10 will be output here. In JavaScript, even if the for loop has ended, the variable i still exists and the last value is recorded. Some developers forget this, which leads to many bugs. We can use let instead of for to eliminate this problem.

3. Memory leaks

You need to monitor memory usage because leaks are difficult to avoid. Memory leaks can occur due to references to non-existent objects or circular references.

  • How to avoid: Focus on the reachability of the object.

  • Accessible objects:

    • Objects accessible from anywhere in the existing call stack

    • Global Object

When an object can be accessed through a reference, it will be saved in memory. The browser's garbage collector will only reclaim objects that are inaccessible.

4. Confused equality judgment

JavaScript automatically converts all variable types in Boolean environments to Boolean types, but this may lead to bugs. Example:

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

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

{} and [] are both objects, and they will be converted to true. In order to prevent bugs, it is recommended to use === and !== for comparison, because type conversion will not be performed implicitly.

5. Inefficient DOM operations

In JavaScript, you can easily operate the DOM (add, modify and delete), but developers often do it very inefficiently. This can lead to bugs because these operations are very computationally intensive. To solve this problem, it is recommended to use Document Fragment if you need to operate multiple DOM elements.

Advertisement: Is your online code really free of bugs? Welcome to use Fundebug for free! We can help you find BUGs as soon as possible!

6. Wrong definition of function in for loop

Example:

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);
    };
}

If We have 10 elements, so clicking on any element will display "Element Number #10"! Because when onclick is called, the for loop has ended, so all i's are 10.

Solution:

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);
}

makeHandler is called immediately when the for loop is executed, obtains the current value i+1, and stores it in in variable num. makeHandlerReturns a function using the num variable that is bound to the element's click event.

7. Wrong inheritance through prototype

If developers do not correctly understand the principles of inheritance, they may write buggy code:

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'

However, if We do the following:

delete secondObj.name;

Then:

console.log(secondObj.name); // -> 输出'undefined'

The result we actually want is to print the default name.

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

BaseObject.prototype.name = 'default';

Every BaseObject inherits the name attribute, and the default value is default. At this time, if the name attribute of secondObj is deleted, searching through the prototype chain will return the correct default value.

var thirdObj = new BaseObject('unique');
console.log(thirdObj.name);  // -> 输出'unique'

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

8. Invalid references in instance methods

Let’s implement a simple constructor to create objects:

var MyObject = function() {}

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

var obj = new MyObject();

For ease of use, we define variableswhoAmI to quote obj.whoAmI:

var whoAmI = obj.whoAmI;

Print it out and see:

console.log(whoAmI);

The console will output:

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

Now we Let’s compare the difference between the two calls:

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"

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

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

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

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

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

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

10. 未能成功使用strict mode

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

  • 更加容易debug

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

  • 避免this隐式转换

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

  • eval()更加安全

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

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

相关推荐:

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

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

JS中offsetWidth的bug及处理方法

The above is the detailed content of 10 common JavaScript bugs and how to fix them. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn