国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

10個(gè)JavaScript常見(jiàn)BUG及修復(fù)方法

FleyX / 887人閱讀

摘要:在中傳入的匿名函數(shù)是在這個(gè)對(duì)象環(huán)境下,所以是指向,但是并沒(méi)有方法。自從年雙十一正式上線(xiàn),累計(jì)處理了億錯(cuò)誤事件,得到了金山軟件等眾多知名用戶(hù)的認(rèn)可。

譯者按: JavaScript語(yǔ)言設(shè)計(jì)太靈活,用起來(lái)不免要多加小心掉進(jìn)坑里面。

原文: Top 10 bugs and their bug fixing

譯者: Fundebug

為了保證可讀性,本文采用意譯而非直譯。另外,本文版權(quán)歸原作者所有,翻譯僅用于學(xué)習(xí)。

如今網(wǎng)站幾乎100%使用JavaScript。JavaScript看上去是一門(mén)十分簡(jiǎn)單的語(yǔ)言,然而事實(shí)并不如此。它有很多容易被弄錯(cuò)的細(xì)節(jié),一不注意就導(dǎo)致BUG。

1. 錯(cuò)誤的對(duì)this進(jìn)行引用

在閉包或則回調(diào)中,this關(guān)鍵字的作用域很容易弄錯(cuò)。舉個(gè)例子:

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

如果執(zhí)行上面的代碼,我們會(huì)看到報(bào)錯(cuò):

Uncaught TypeError: undefined is not a function

出錯(cuò)的原因在于:當(dāng)你調(diào)用setTimeout函數(shù),你實(shí)際上調(diào)用的是window.setTimeout()。在setTimeout中傳入的匿名函數(shù)是在window這個(gè)對(duì)象環(huán)境下,所以this是指向window,但是window并沒(méi)有clearBoard方法。

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

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

或則使用bind()函數(shù):

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)有關(guān)的BUG

在大多數(shù)程序語(yǔ)言中,每一個(gè)函數(shù)塊都有一個(gè)獨(dú)立的新的作用域,但是在JavaScript中并不是。例如:

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

通常在這種情況下,調(diào)用console.log()會(huì)輸出undefined或則報(bào)錯(cuò)。不過(guò)呢,這里會(huì)輸出10。在JavaScript中,即使for循環(huán)已經(jīng)結(jié)束,變量i依然存在,并且記錄最后的值。有些開(kāi)發(fā)者會(huì)忘記這一點(diǎn),然后導(dǎo)致許多bug。我們可以使用let而不是var來(lái)杜絕這一問(wèn)題。

3. 內(nèi)存泄漏

你需要監(jiān)控內(nèi)存使用量,因?yàn)樾孤逗茈y避免。內(nèi)存泄露可能由于引用不存在的對(duì)象或則循環(huán)引用導(dǎo)致。

如何避免:關(guān)注對(duì)象的可訪(fǎng)問(wèn)性(reachability)。

可訪(fǎng)問(wèn)的對(duì)象:

現(xiàn)有的call stack任何位置可以訪(fǎng)問(wèn)的對(duì)象

全局對(duì)象

當(dāng)一個(gè)對(duì)象可以通過(guò)引用訪(fǎng)問(wèn)到,那么會(huì)在內(nèi)存中保存。瀏覽器的垃圾回收器僅僅會(huì)把那些不可訪(fǎng)問(wèn)的對(duì)象回收。

4. 混淆的相等判斷

JavaScript自動(dòng)將所有在布爾環(huán)境下的變量類(lèi)型轉(zhuǎn)換為布爾類(lèi)型,但是可能導(dǎo)致bug。舉例:

// 所有都是true
console.log(false == "0");
console.log(null == undefined);
console.log(" 	
" == 0);
console.log("" == 0);

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

{}[]都是對(duì)象,他們都會(huì)被轉(zhuǎn)換為true。為了防止bug出現(xiàn),推薦使用===!==來(lái)做比較,因?yàn)椴粫?huì)隱式做類(lèi)型轉(zhuǎn)換。

5. 低效的DOM操作

在JavaScript中,你可以輕松操作DOM(添加、修改和刪除),但是開(kāi)發(fā)者往往很低效地去操作。這會(huì)導(dǎo)致bug出現(xiàn),因?yàn)檫@些操作非常耗費(fèi)計(jì)算資源。為了解決這個(gè)問(wèn)題,推薦使用文檔碎片(Document Fragment),如果你需要操作多個(gè)DOM元素。

廣告: 你的線(xiàn)上代碼真的沒(méi)有BUG嗎?歡迎免費(fèi)使用Fundebug!我們可以幫助您第一時(shí)間發(fā)現(xiàn)BUG!

6. 在for循環(huán)中錯(cuò)誤的定義函數(shù)

舉例:

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

如果我們有10個(gè)元素,那么點(diǎn)擊任何一個(gè)元素都會(huì)顯示“元素編號(hào)#10”!因?yàn)樵?b>onclick被調(diào)用的時(shí)候,for循環(huán)已經(jīng)結(jié)束,因此所有的i都是10。

解法:

var elements = document.getElementsByTagName("input");
var n = elements.length;    // 假設(shè)有10個(gè)元素
var makeHandler = function(num) {  // outer function
     return function() {   // inner function
         console.log("元素編號(hào)##" + num);
     };
};
for (var i = 0; i < n; i++) {
    elements[i].onclick = makeHandler(i+1);
}

makeHandler在for循環(huán)執(zhí)行的時(shí)候立即被調(diào)用,獲取到當(dāng)前的值i+1,并且存儲(chǔ)在變量num中。makeHandler返回一個(gè)函數(shù)使用num變量,該函數(shù)被綁定到元素的點(diǎn)擊事件。

7. 通過(guò)原型錯(cuò)誤地繼承

開(kāi)發(fā)者如果沒(méi)能正確理解繼承的原理,那么就可能寫(xiě)出有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"

而我們實(shí)際上想要的結(jié)果是打印默認(rèn)的name。

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

BaseObject.prototype.name = "default";

每一個(gè)BaseObject都繼承name屬性,并且默認(rèn)值為default。此時(shí)如果secondObjname屬性被刪除掉,通過(guò)原型鏈查找會(huì)返回正確的默認(rèn)值。

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

delete thirdObj.name;
console.log(thirdObj.name);  // -> 輸出"default"
8. 實(shí)例方法中的無(wú)效引用

我們來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的構(gòu)造函數(shù)用來(lái)創(chuàng)建對(duì)象:

var MyObject = function() {}

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

var obj = new MyObject();

為了使用方便,我們定義變量whoAmI來(lái)引用obj.whoAmI

var whoAmI = obj.whoAmI;

打印出來(lái)看看:

console.log(whoAmI);

控制臺(tái)會(huì)輸出:

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

現(xiàn)在我們來(lái)對(duì)比一下兩者調(diào)用的區(qū)別:

obj.whoAmI();  // 輸出"MyObj" (和期望一致)
whoAmI();      // 輸出"window" (竟然輸出了window)

當(dāng)我們把obj.whoAmI賦值給whoAmI的時(shí)候,這個(gè)新的變量whoAmI是定義在全局下,因此this指向全局的window,而不是MyObj。如果我們真的要獲取對(duì)MyObj的函數(shù)的引用,需要在其作用域下。

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函數(shù)第一個(gè)參數(shù)誤用字符串

如果你將一個(gè)字符串作為setTimeout/setTimeInterval,它會(huì)被傳給函數(shù)構(gòu)造函數(shù)并構(gòu)建一個(gè)新的函數(shù)。該操作流程很慢而且低效,并導(dǎo)致bug出現(xiàn)。

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

一個(gè)好的替代方法就是傳入函數(shù)作為參數(shù):

setInterval(logTime, 1000);   // 將logTime函數(shù)傳入

setTimeout(function() {       // 傳入一個(gè)匿名函數(shù)
    logMessage(msgValue);     
  }, 1000);
10. 未能成功使用strict mode

使用strict model會(huì)增加很多限制條件來(lái)加強(qiáng)安全和防止某些錯(cuò)誤的出現(xiàn),如果不使用strict mode,你就相當(dāng)于少了一個(gè)得力的助手幫你避免錯(cuò)誤:

更加容易debug

避免不小心定義了不該定義的全局變量

避免this隱式轉(zhuǎn)換

避免屬性名字或則參數(shù)值的重復(fù)使用

eval()更加安全

無(wú)效地使用delete會(huì)自動(dòng)拋出錯(cuò)誤

關(guān)于Fundebug

Fundebug專(zhuān)注于JavaScript、微信小程序、微信小游戲、支付寶小程序、React Native、Node.js和Java實(shí)時(shí)BUG監(jiān)控。 自從2016年雙十一正式上線(xiàn),F(xiàn)undebug累計(jì)處理了6億+錯(cuò)誤事件,得到了Google、360、金山軟件等眾多知名用戶(hù)的認(rèn)可。歡迎免費(fèi)試用!

版權(quán)聲明

轉(zhuǎn)載時(shí)請(qǐng)注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/11/15/top_10_bugs_and_fixing_method/

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/90201.html

相關(guān)文章

  • JavaScript 調(diào)試常見(jiàn)報(bào)錯(cuò)以修復(fù)方法

    摘要:表示錯(cuò)誤沒(méi)有被語(yǔ)句捕獲,是錯(cuò)誤的名字。如何修復(fù)錯(cuò)誤確保方法名正確。這個(gè)錯(cuò)誤的行號(hào)將指出正確的位置。相關(guān)錯(cuò)誤代碼調(diào)用的方法在當(dāng)前狀態(tài)無(wú)法調(diào)用。通常由引起,在方法準(zhǔn)備完畢之前調(diào)用它會(huì)引起錯(cuò)誤。原文翻譯出處涂鴉碼農(nóng)錯(cuò)誤以及如何修復(fù) (看到一篇調(diào)試JS很有用的文章,收藏一下) JavaScript 調(diào)試是一場(chǎng)噩夢(mèng):首先給出的錯(cuò)誤非常難以理解,其次給出的行號(hào)不總有幫助。有個(gè)查找錯(cuò)誤含義,及修復(fù)...

    zhongmeizhi 評(píng)論0 收藏0
  • JS干貨| 瀏覽器缺陷、瀏覽器的缺陷修復(fù)等五大開(kāi)發(fā)問(wèn)題解決之道

    摘要:圖對(duì)可復(fù)用代碼挑戰(zhàn)最大的五項(xiàng)問(wèn)題五大開(kāi)發(fā)問(wèn)題如下。瀏覽器的缺陷修復(fù)。瀏覽器缺失的功能。復(fù)雜的地方是,當(dāng)前瀏覽器會(huì)在未來(lái)的瀏覽器版本中被修復(fù)。假設(shè)瀏覽器引起常見(jiàn)的網(wǎng)站問(wèn)題為解決瀏覽器使用特殊技巧,將來(lái)瀏覽器發(fā)布新版本修復(fù)了,就會(huì)出現(xiàn)問(wèn)題。 任意一段重要的代碼都需要關(guān)注無(wú)數(shù)的開(kāi)發(fā)問(wèn)題。但是,其中對(duì)可復(fù)用JavaScript代碼挑戰(zhàn)最大的五項(xiàng)問(wèn)題如圖14.2所示。 showImg(https...

    qiangdada 評(píng)論0 收藏0
  • javascript 代碼規(guī)范

    目錄 1.為什要遵守代碼規(guī)范 2.編寫(xiě)代碼需遵守的幾個(gè)原則 3.編碼規(guī)范(Coding Conventions) 4.命名規(guī)范(Naming Conventions) 5.css基礎(chǔ)class類(lèi) 1.為什要遵守代碼規(guī)范 軟件bug的修復(fù)是昂貴的,并且隨著時(shí)間的推移,這些bug的成本也會(huì)增加,尤其當(dāng)這些bug潛伏并慢慢出現(xiàn)在已經(jīng)發(fā)布的軟件中時(shí)。當(dāng)你發(fā)現(xiàn)bug 的時(shí)候就立即修復(fù)它是最好的,此時(shí)你代...

    cnsworder 評(píng)論0 收藏0
  • Fundebug前端JavaScript插件更新至1.8.2,修復(fù)2個(gè)BUG

    摘要:前端異常監(jiān)控插件更新至,修復(fù)了個(gè)小修復(fù)用戶(hù)行為中重復(fù)記錄請(qǐng)求的修復(fù)的為報(bào)錯(cuò)的這個(gè)都不會(huì)影響功能,不過(guò)為了避免造成困擾,請(qǐng)大家及時(shí)更新插件。 摘要: 修復(fù)2個(gè)BUG,請(qǐng)大家及時(shí)更新。 showImg(https://segmentfault.com/img/remote/1460000019373421?w=900&h=383); Fundebug前端異常監(jiān)控服務(wù) Fundebug是專(zhuān)業(yè)...

    lifesimple 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<