成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

10個JavaScript常見BUG及修復方法

新聞 前端
如今網站幾乎100%使用JavaScript。JavaScript看上去是一門十分簡單的語言,然而事實并不如此。它有很多容易被弄錯的細節,一不注意就導致BUG。

譯者按:JavaScript語言設計太靈活,用起來不免要多加小心掉進坑里面。

原文: Top 10 bugs and their bug fixing

譯者: Fundebug

為了保證可讀性,本文采用意譯而非直譯。另外,本文版權歸原作者所有,翻譯僅用于學習。

如今網站幾乎100%使用JavaScript。JavaScript看上去是一門十分簡單的語言,然而事實并不如此。它有很多容易被弄錯的細節,一不注意就導致BUG。

1. 錯誤的對this進行引用

在閉包或則回調中, this 關鍵字的作用域很容易弄錯。舉個例子:

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

如果執行上面的代碼,我們會看到報錯:

Uncaught TypeError: undefined is not a function

出錯的原因在于:當你調用 setTimeout 函數,你實際上調用的是 window.setTimeout() 。在 setTimeout 中傳入的匿名函數是在 window 這個對象環境下,所以 this 是指向 window ,但是 window 并沒有 clearBoard 方法。

如何解決呢?定義新的變量引用指向 Game 對象的 this ,然后就可以使用啦。

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

或則使用 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的引用正確
};

2. 和塊作用域(block scope)有關的BUG

在大多數程序語言中,每一個函數塊都有一個獨立的新的作用域,但是在JavaScript中并不是。例如:

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

通常在這種情況下,調用 console.log() 會輸出 undefined 或則報錯。不過呢,這里會輸出 10 。在JavaScript中,即使for循環已經結束,變量 i 依然存在,并且記錄最后的值。有些開發者會忘記這一點,然后導致許多bug。我們可以使用 let 而不是 for 來杜絕這一問題。

3. 內存泄漏

你需要監控內存使用量,因為泄露很難避免。內存泄露可能由于引用不存在的對象或則循環引用導致。

  • 如何避免:關注對象的可訪問性(reachability)。
  • 可訪問的對象:

    • 現有的call stack任何位置可以訪問的對象
    • 全局對象

當一個對象可以通過引用訪問到,那么會在內存中保存。瀏覽器的垃圾回收器僅僅會把那些不可訪問的對象回收。

4. 混淆的相等判斷

JavaScript自動將所有在布爾環境下的變量類型轉換為布爾類型,但是可能導致bug。舉例:

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

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

{} 和 [] 都是對象,他們都會被轉換為true。為了防止bug出現,推薦使用 === 和 !== 來做比較,因為不會隱式做類型轉換。

5. 低效的DOM操作

在JavaScript中,你可以輕松操作DOM(添加、修改和刪除),但是開發者往往很低效地去操作。這會導致bug出現,因為這些操作非常耗費計算資源。為了解決這個問題,推薦使用文檔碎片(Document Fragment),如果你需要操作多個DOM元素。

廣告: 你的線上代碼真的沒有BUG嗎?歡迎免費使用 Fundebug !我們可以幫助您第一時間發現BUG!

6. 在for循環中錯誤的定義函數

舉例:

var elements = document.getElementsByTagName('input');
var n = elements.length;    // 假設我們有10個元素
for (var i = 0; i < n; i++) {
    elements[i].onclick = function() {
        console.log("元素編號#" + i);
    };
}

如果我們有10個元素,那么點擊任何一個元素都會顯示“元素編號#10”!因為在 onclick 被調用的時候,for循環已經結束,因此所有的i都是10。

解法:

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 在for循環執行的時候立即被調用,獲取到當前的值 i+1 ,并且存儲在變量 num中。 makeHandler 返回一個函數使用 num 變量,該函數被綁定到元素的點擊事件。

7. 通過原型錯誤地繼承

開發者如果沒能正確理解繼承的原理,那么就可能寫出有bug的代碼:

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'

但是,如果我們做如下操作:

delete secondObj.name;

那么:

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

而我們實際上想要的結果是打印默認的name。

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

BaseObject.prototype.name = 'default';

每一個 BaseObject 都繼承 name 屬性,并且默認值為 default 。此時如果 secondObj 的 name 屬性被刪除掉,通過原型鏈查找會返回正確的默認值。

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

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

8. 實例方法中的無效引用

我們來實現一個簡單的構造函數用來創建對象:

var MyObject = function() {}

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

var obj = new MyObject();

為了使用方便,我們定義變量 whoAmI 來引用 obj.whoAmI :

var whoAmI = obj.whoAmI;

打印出來看看:

console.log(whoAmI);

控制臺會輸出:

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"

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會自動拋出錯誤   

版權聲明:

轉載時請注明作者Fundebug以及本文地址:

https://blog.fundebug.com/2017/11/15/top_10_bugs_and_fixing_method/

 

責任編輯:張燕妮 來源: SegmentFault
相關推薦

2024-12-06 11:42:33

2018-06-27 10:07:28

2013-07-23 06:03:01

Android開發BuAmdroid開發學習Android開發Bu

2024-07-16 08:00:00

Kubernetes開發

2020-10-14 10:41:24

安全漏洞數據

2018-11-15 11:00:27

Python漏洞修復

2010-06-17 09:39:07

Ubuntu Grub

2010-06-13 12:59:15

Ubuntu xp G

2010-06-12 11:26:21

Grub Rescue

2022-01-14 23:42:30

Windows 10Windows微軟

2011-01-24 13:36:11

網絡故障修復

2019-11-01 15:33:00

JavaScript面試開發

2018-02-02 08:35:12

Windows 10原始版升級

2021-07-16 23:13:10

Windows 10Windows微軟

2009-04-27 23:45:07

2023-06-16 15:17:21

sprint工具

2023-01-07 17:56:21

Windows 10安全補丁

2022-02-09 08:21:43

累積更新微軟Windows 10

2014-12-17 09:40:22

dockerLinuxPaaS

2010-10-13 11:19:11

MySQL數據文件
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品www | 看羞羞视频 | 国产精选一区 | 91精品无人区卡一卡二卡三 | 中文在线一区二区 | 国产成人精品在线 | 中文字幕一区二区三区乱码在线 | 99久久久无码国产精品 | 九九热精品视频 | 97人人澡人人爽91综合色 | 福利视频三区 | 精品久久久久久红码专区 | 精品福利一区二区三区 | 国产在线www | 成人h电影在线观看 | 一区二区三区四区在线视频 | 嫩草研究影院 | 请别相信他免费喜剧电影在线观看 | 剑来高清在线观看 | 性做久久久久久免费观看欧美 | 国产精品视频在线观看 | 久久久久久久综合 | 亚洲福利av | 欧美综合在线观看 | 欧美一区二区在线 | 亚洲一区中文 | 在线观看视频你懂得 | 在线播放第一页 | 一区二区三区视频在线观看 | 久久精品免费观看 | 亚洲一区二区综合 | 干干干操操操 | 精品一区二区三区在线观看国产 | 中文字幕一区二区三区精彩视频 | 欧美黄色片在线观看 | 午夜私人影院在线观看 | 九九视频在线观看视频6 | 欧美激情视频一区二区三区在线播放 | 一区二区三区回区在观看免费视频 | 精品欧美一区二区在线观看视频 | 免费一级淫片aaa片毛片a级 |