成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

詳解1000+項(xiàng)目數(shù)據(jù)分析出來(lái)的10大JavaScript錯(cuò)誤

jubincn / 959人閱讀

摘要:當(dāng)未捕獲的錯(cuò)誤通過(guò)處理程序引發(fā)的錯(cuò)誤,而不是捕獲在中被瀏覽器的跨域策略限制時(shí),會(huì)產(chǎn)生這類(lèi)的腳本錯(cuò)誤。例如,如果您將您的代碼托管在上,則任何未被捕獲的錯(cuò)誤將被報(bào)告為腳本錯(cuò)誤而不是包含有用的堆棧信息。

譯者按: null/undefined引發(fā)的錯(cuò)誤在10大錯(cuò)誤中比例很高。而它們很可能導(dǎo)致嚴(yán)重問(wèn)題,所以要重視起來(lái)。

原文: Top 10 JavaScript errors from 1000+ projects (and how to avoid them)

譯者: Fundebug

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

為了回饋擁護(hù)我們的開(kāi)發(fā)者,我們將所有項(xiàng)目數(shù)據(jù)分析了一下,總結(jié)出10大JavaScript錯(cuò)誤。我們會(huì)詳細(xì)解釋錯(cuò)誤的原因以及如何預(yù)防再次發(fā)生。如果你學(xué)會(huì)了避開(kāi)這些坑,那么你將會(huì)是一個(gè)更加出色的開(kāi)發(fā)者。

如今數(shù)據(jù)為王,我們聚合了大量BUG數(shù)據(jù),并對(duì)它們進(jìn)行分析,列出了排名前十的JavaScript錯(cuò)誤。Rollbar收集每一個(gè)項(xiàng)目所有的錯(cuò)誤,并統(tǒng)計(jì)它們發(fā)生的次數(shù)。我們將相同的錯(cuò)誤聚合起來(lái)。如果同一個(gè)錯(cuò)誤出現(xiàn)很多次的話(huà),這樣就可以避免像日志一樣非常多,讓人無(wú)從下手。

我們將統(tǒng)計(jì)同一個(gè)錯(cuò)誤在多少個(gè)項(xiàng)目中出現(xiàn),并以此來(lái)排序。如下所示:

為了方便閱讀,每一條錯(cuò)誤我們將后面的內(nèi)容做了適當(dāng)省略。接下來(lái)我們?cè)敿?xì)介紹每一個(gè)錯(cuò)誤。

1. Uncaught TypeError: Cannot read property

如果你是一個(gè)JavaScript開(kāi)發(fā)者,這種錯(cuò)誤大概你已經(jīng)見(jiàn)怪不怪了。在Chrome下,當(dāng)你從一個(gè)不存在的對(duì)象(undefined)獲取屬性或則進(jìn)行函數(shù)調(diào)用,就會(huì)報(bào)這樣的錯(cuò)。你可以在Chrome瀏覽器控制臺(tái)測(cè)試:

有很多種原因可以導(dǎo)致這種情況的出現(xiàn),一個(gè)常見(jiàn)的情況是在渲染UI部件的時(shí)候,沒(méi)有正確地初始化狀態(tài)(state)。我們來(lái)看一個(gè)真實(shí)的例子。在這里我選用React,不過(guò)內(nèi)在的原理同樣適用于Angular、Vue或則其它框架。

class Quiz extends Component {
  componentWillMount() {
    axios.get("/thedata").then(res => {
      this.setState({items: res.data});
    });
  }

  render() {
    return (
      
    {this.state.items.map(item =>
  • {item.name}
  • )}
); } }

這里有兩個(gè)關(guān)鍵點(diǎn):

組件的狀態(tài)(state)(this.state)沒(méi)有初始化,值為undefined

如果使用異步的方式獲取數(shù)據(jù),那么在數(shù)據(jù)加載前,該組件已經(jīng)至少渲染一次。這和componentWillMount或則componentDidMount是否獲取數(shù)據(jù)無(wú)關(guān)。也就是說(shuō),當(dāng)Quiz第一次渲染的時(shí)候,this.state.items是未定義的。因此,會(huì)報(bào)錯(cuò):"Uncaught TypeError: Cannot read property ‘map’ of undefined" 。

這個(gè)bug很容易修復(fù)。最簡(jiǎn)單的方法:在構(gòu)造函數(shù)中初始化state。

class Quiz extends Component {
  // Added this:
  constructor(props) {
    super(props);

    // Assign state itself, and a default value for items
    this.state = {
      items: []
    };
  }

  componentWillMount() {
    axios.get("/thedata").then(res => {
      this.setState({items: res.data});
    });
  }

  render() {
    return (
      
    {this.state.items.map(item =>
  • {item.name}
  • )}
); } }

也許在你的應(yīng)用中會(huì)有點(diǎn)不一樣,不夠希望能夠給你一些線(xiàn)索幫助你去修復(fù)或則避免這樣的問(wèn)題。如果沒(méi)有,那么繼續(xù)往下看吧,還有更多相關(guān)的例子等著你呢。

2. TypeError: ‘undefined’ is not an object (evaluating

在Safari下,如果在一個(gè)未定義(undefined)的對(duì)象上讀取屬性或則調(diào)用函數(shù),就會(huì)觸發(fā)這樣的錯(cuò)誤。你可以在Safari控制臺(tái)測(cè)試。這個(gè)錯(cuò)誤根本上來(lái)說(shuō)和第一個(gè)在Chrome下的錯(cuò)誤是一樣的,只是錯(cuò)誤的消息不同。

備注:Fundebug早已機(jī)智地將這兩種情況聚合為一個(gè)錯(cuò)誤了,更加方便分析,歡迎各位老鐵試用!

3. TypeError: null is not an object (evaluating

在Safari下,如果你嘗試從null讀取屬性或則調(diào)用方法,就會(huì)報(bào)錯(cuò)。如下:

有趣的是,在JavaScript中,null和undefined是不同的,所以我們看到兩個(gè)不同的錯(cuò)誤消息。Undefined指的是一個(gè)變量沒(méi)有被賦值,而null指的是值為空。我們可以用===來(lái)判斷:

一種現(xiàn)實(shí)中可能的情況就是:如果你嘗試在一個(gè)DOM元素加載之前使用它。那么DOM API就會(huì)返回null。任何處理DOM元素的JS代碼都應(yīng)當(dāng)在DOM加載完畢之后調(diào)用。JS代碼是按照代碼的順序從上往下依次解釋執(zhí)行。如果在DOM元素前有腳本,那么在瀏覽器分析HTML頁(yè)面的時(shí)候,JS代碼也在執(zhí)行了。如果JS代碼執(zhí)行的時(shí)候,DOM還沒(méi)有創(chuàng)建好,那么你會(huì)遇到這個(gè)錯(cuò)誤。

最常用的解法是使用事件監(jiān)聽(tīng),當(dāng)DOM加載完畢之后,再觸發(fā)JS代碼的執(zhí)行。



來(lái)自網(wǎng)友的備注:

上面說(shuō)的這個(gè)問(wèn)題,是因?yàn)樵趆tml中所有資源的加載都是從上而下同步加載的,所以以前的代碼規(guī)范都會(huì)有一句:”在html里css標(biāo)簽放上面,js標(biāo)簽放下面“;包括比如jQuery里的ready方法,這些做法都是為了保證js代碼執(zhí)行的時(shí)候,頁(yè)面上的dom元素都是創(chuàng)建好了的。

這里我再介紹一下defer和async,在外鏈引入js文件的情況,可以在script標(biāo)簽上加上defer或async修飾符,使該js能夠異步加載,從而解決上面遇到的問(wèn)題。async表示后續(xù)的解析任務(wù)和當(dāng)前js標(biāo)簽的加載任務(wù)并行執(zhí)行,defer表示該js標(biāo)簽的代碼會(huì)在所有頁(yè)面元素解析完成之后,DOMContentLoaded 事件觸發(fā)之前執(zhí)行。兩者具體區(qū)別參考:https://segmentfault.com/q/1010000000640869。

4. (unknown): Script error

當(dāng)未捕獲的 JavaScript 錯(cuò)誤(通過(guò)window.onerror處理程序引發(fā)的錯(cuò)誤,而不是捕獲在try-catch中)被瀏覽器的跨域策略限制時(shí),會(huì)產(chǎn)生這類(lèi)的腳本錯(cuò)誤。 例如,如果您將您的 JavaScript 代碼托管在 CDN 上,則任何未被捕獲的錯(cuò)誤將被報(bào)告為“腳本錯(cuò)誤” 而不是包含有用的堆棧信息。這是一種瀏覽器安全措施,旨在防止跨域傳遞數(shù)據(jù),否則將不允許進(jìn)行通信。

想要獲取到真實(shí)詳細(xì)的錯(cuò)誤信息,你可以像這樣做:

在header里添加 Access-Control-Allow-Origin 字段
在header(這應(yīng)該是服務(wù)器返回的response header)字段里,把Access-Control-Allow-Origin設(shè)為,這樣就表示來(lái)自任意的域名請(qǐng)求都可以正確地訪(fǎng)問(wèn)到服務(wù)器的資源。必要的話(huà)也可以指定具體的域名來(lái)代替星號(hào),比如:Access-Control-Allow-Origin: www.example.com。但是配置的域名太多的話(huà),處理起來(lái)會(huì)有點(diǎn)棘手,而且如果你在使用CDN的話(huà)還會(huì)出現(xiàn)緩存的問(wèn)題,這樣就有點(diǎn)費(fèi)力不討好了。更多參考這里。

下面舉一些在各種環(huán)境下配置這個(gè)header的示例:

Apache
在JavaScript代碼所在的文件夾目錄下,新建一個(gè).htaccess文件,內(nèi)容如下:

Header add Access-Control-Allow-Origin "*"

Nginx
在JavaScript代碼所在文件夾目錄下面,添加add_header命令:

location ~ ^/assets/ {
  add_header Access-Control-Allow-Origin *;
}```

HAProxy
在后端的JavaScript所在文件加入以下內(nèi)容:

rspadd Access-Control-Allow-Origin: *

在JavaScript標(biāo)簽上設(shè)置crossorigin="anonymous"
在html代碼里,每個(gè)設(shè)置好了Access-Control-Allow-Origin的js資源,都可以在其JavaScript標(biāo)簽上添加crossorigin="anonymous"。在設(shè)置crossorigin="anonymous"之前,確定好header字段都是正確發(fā)送了的。在Firefox里,如果js標(biāo)簽上出現(xiàn)了crossorigin屬性,但是header里沒(méi)有Access-Control-Allow-Origin,那么該js將不會(huì)被執(zhí)行。(crossorigin是html5新增的功能,不只是JavaScript標(biāo)簽獨(dú)有的,比如video、image也可以設(shè)置)

5. TypeError: Object doesn’t support property

在IE中,如果調(diào)用未定義的方法就會(huì)發(fā)生這種錯(cuò)誤。您可以在IE開(kāi)發(fā)者控制臺(tái)中進(jìn)行測(cè)試。

相當(dāng)于 Chrome 中的 “TypeError:”undefined“ is not a function” 錯(cuò)誤。 對(duì)于相同的錯(cuò)誤,不同的瀏覽器具有不同的錯(cuò)誤消息。

在IE里使用JavaScript的命名空間時(shí),就很容易碰到這個(gè)錯(cuò)誤。發(fā)生這個(gè)錯(cuò)誤十有八九是因?yàn)镮E無(wú)法將當(dāng)前命名空間里的方法綁定到this關(guān)鍵字上。例如,假設(shè)有個(gè)命名空間Rollbar,它有一個(gè)方法叫isAwesome()。在Rollbar命名空間中,可以直接使用this關(guān)鍵字來(lái)調(diào)用這個(gè)方法:

this.isAwesome();

在Chrome、Firefox和Opera中這樣做都是沒(méi)有問(wèn)題的,但在IE中就不行。所以,最安全的做法是指定全命名空間:

Rollbar.isAwesome();
6. TypeError: ‘undefined’ is not a function

在Chrome下,調(diào)用一個(gè)未定義的函數(shù)時(shí)就會(huì)發(fā)生這個(gè)錯(cuò)誤,可以在Chrome/Mozilla開(kāi)發(fā)者控制臺(tái)測(cè)試:

隨著js代碼的編碼技巧和設(shè)計(jì)模式越來(lái)越復(fù)雜,在回調(diào)函數(shù)、閉包等各種作用域中this的指向的層級(jí)也隨之增加,這就是js代碼中this/that指向容易混淆的原因。

比如下面這段代碼:

function testFunction() {
 this.clearLocalStorage();
 this.timer = setTimeout(function() {
  this.clearBoard();  // 這里的”this"是指什么?
 }, 0);
};

執(zhí)行上面的代碼會(huì)報(bào)錯(cuò):“Uncaught TypeError: undefined is not a function”。因?yàn)樵谡{(diào)用setTimeout()方法時(shí),實(shí)際上是在調(diào)用window.setTimeout()。傳給setTimeout()的匿名函數(shù)的this實(shí)際上是window,而window并不包含clearBoard()方法。

一個(gè)最簡(jiǎn)單的、能兼容舊版本瀏覽器的方法,就是先把this指向賦值給一個(gè)變量self,然后在閉包里直接引用這個(gè)self變量。例如:

function testFunction () {
 this.clearLocalStorage();
 var self = this;  // 將this賦值給self
 this.timer = setTimeout(function(){
  self.clearBoard();  
 }, 0);
};

也可以使用bind方法來(lái)傳遞this:

function testFunction () {
  this.clearLocalStorage();
  this.timer = setTimeout(this.reset.bind(this), 0);  // bind to "this"
};

function testFunction(){
    this.clearBoard();    //back in the context of the right "this"!
};
7. Uncaught RangeError: Maximum call stack

在Chrome里,有幾種情況會(huì)發(fā)生這個(gè)錯(cuò)誤,其中一個(gè)就是函數(shù)的遞歸調(diào)用,并且不能終止。這個(gè)錯(cuò)誤可以在Chrome開(kāi)發(fā)者控制臺(tái)重現(xiàn)。

還有,如果傳給函數(shù)的值超出可接受的范圍時(shí),也會(huì)出現(xiàn)這個(gè)錯(cuò)誤。很多函數(shù)只接受指定范圍的數(shù)值,例如,Number.toExponential(digits)和Number.toFixed(digits)方法,只接受0到20的數(shù)值,而Number.toPrecision(digits)只接受1到21的數(shù)值。

var a = new Array(4294967295);  //OK
var b = new Array(-1); //range error

var num = 2.555555;
document.writeln(num.toExponential(4));  //OK
document.writeln(num.toExponential(-2)); //range error!

num = 2.9999;
document.writeln(num.toFixed(2));   //OK
document.writeln(num.toFixed(25));  //range error!

num = 2.3456;
document.writeln(num.toPrecision(1));   //OK
document.writeln(num.toPrecision(22));  //range error!

來(lái)自網(wǎng)友的備注:

我在chorme測(cè)試時(shí),發(fā)現(xiàn)上述的第二種參數(shù)超出范圍的情況,錯(cuò)誤信息并不是”Maximum call stack“,并且Number.toExponential(digits) 和 Number.toFixed(digits)方法,接收的范圍應(yīng)該是0到100

另外,如果遞歸層數(shù)太多,會(huì)導(dǎo)致內(nèi)存溢出。那么如何防止呢?可以尾調(diào)用優(yōu)化,函數(shù)結(jié)尾改成尾遞歸,具體內(nèi)容參考這里,文中提到的一個(gè)觀念就是使用尾遞歸來(lái)避免棧溢出,遺憾的是目前js還是無(wú)法支持"尾調(diào)用優(yōu)化"。

8. TypeError: Cannot read property ‘length’

在Chrome中,如果讀取未定義變量的長(zhǎng)度屬性,會(huì)報(bào)錯(cuò)。

如果數(shù)組未初始化,或者因?yàn)樽饔糜虻膯?wèn)題而沒(méi)有正確地獲取到,則可能會(huì)遇到此錯(cuò)誤。讓我們用下面的例子來(lái)理解這個(gè)錯(cuò)誤。

var testArray= ["Test"];

function testFunction(testArray) {
    for (var i = 0; i < testArray.length; i++) {
      console.log(testArray[i]);
    }
}

testFunction();

函數(shù)的參數(shù)名會(huì)覆蓋全局的變量名。也就是說(shuō),全局的testArray被函數(shù)的參數(shù)名覆蓋了,所以在函數(shù)體里訪(fǎng)問(wèn)到的是本地的testArray,但本地并沒(méi)有定義testArray,所以出現(xiàn)了這個(gè)錯(cuò)誤。

有兩種方法可用于解決這個(gè)問(wèn)題:

將函數(shù)的參數(shù)移除

var testArray = ["Test"];

/* Precondition: defined testArray outside of a function */
function testFunction(/* No params */) {
    for (var i = 0; i < testArray.length; i++) {
      console.log(testArray[i]);
    }
}

testFunction();

把外部的變量傳給函數(shù)testFunction函數(shù)

var testArray = ["Test"];
function testFunction(testArray) {
    for (var i = 0; i < testArray.length; i++) {
      console.log(testArray[i]);
    }
}
testFunction(testArray);

9. Uncaught TypeError: Cannot set property

如果對(duì)undefined變量進(jìn)行賦值或讀取操作,會(huì)拋出“Uncaught TypeError: cannot set property of undefined”異常。

因?yàn)閠est對(duì)象不存在,就會(huì)拋出“Uncaught TypeError: cannot set property of undefined”異常。

10. ReferenceError: event is not defined

當(dāng)訪(fǎng)問(wèn)一個(gè)未定義的對(duì)象或超出當(dāng)前作用域的對(duì)象,就會(huì)發(fā)生這個(gè)錯(cuò)誤。

如果在使用事件處理系統(tǒng)時(shí)遇到此錯(cuò)誤,請(qǐng)確保使用傳入的事件對(duì)象作為參數(shù)。舊瀏覽器(IE)提供了全局的event變量,但并不是所有的瀏覽器都支持。像jQuery這樣的庫(kù)試圖規(guī)范化這種行為。盡管如此,最好使用傳入事件處理函數(shù)的函數(shù)。

function myFunction(event) {
    event = event.which || event.keyCode;
    if(event.keyCode===13){
       alert(event.keyCode);
    }
}
結(jié)論

看到這里,你會(huì)發(fā)現(xiàn)這十大錯(cuò)誤幾乎都是null/undefined錯(cuò)誤。如果有一個(gè)好的靜態(tài)類(lèi)型檢查系統(tǒng),比如使用TypeScript可以幫助你在編譯的時(shí)候就發(fā)現(xiàn)問(wèn)題。如果沒(méi)有使用TypeScript,那么請(qǐng)多多使用條件語(yǔ)句做判斷,防止這種情況出現(xiàn)。

在生產(chǎn)環(huán)境中會(huì)出現(xiàn)各種不可預(yù)期的錯(cuò)誤。關(guān)鍵是要及時(shí)發(fā)現(xiàn)那些影響用戶(hù)體驗(yàn)的錯(cuò)誤,并使用適當(dāng)?shù)墓ぞ呖焖侔l(fā)現(xiàn)和解決這些問(wèn)題。Fundebug提供網(wǎng)站bug監(jiān)控,助你實(shí)時(shí)發(fā)現(xiàn)bug。

版權(quán)聲明:
轉(zhuǎn)載時(shí)請(qǐng)注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2018/03/12/top-10-javascript-errors-from-1000-projects/

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/93641.html

相關(guān)文章

  • javascript性能優(yōu)化方面知識(shí)總結(jié)

    摘要:插入迭代器如前面兩條語(yǔ)句可以寫(xiě)成使用直接量替換為替換為替換為如果要?jiǎng)?chuàng)建具有一些特性的一般對(duì)象,也可以使用字面量,如下前面的代碼可用對(duì)象字面量來(lái)改寫(xiě)成這樣使用優(yōu)化多次一旦需要更新請(qǐng)考慮使用文檔碎片來(lái)構(gòu)建結(jié)構(gòu),然后再將其添加到現(xiàn)存的文檔中。 好贊,收藏自 總結(jié)的js性能優(yōu)化方面的小知識(shí)(不喜勿噴) 前言 一直在學(xué)習(xí)javascript,也有看過(guò)《犀利開(kāi)發(fā)Jquery內(nèi)核詳解與實(shí)踐》,對(duì)...

    BlackHole1 評(píng)論0 收藏0
  • 【周刊-2】三年廠面試官-前端面試題(偏難)

    摘要:前言在大廠工作了年,當(dāng)了年的前端面試官,把大廠常問(wèn)的面試題與答案匯總在我的中。第題如何劫持的請(qǐng)求,提供思路難度阿里騰訊很多人在上搜索前端面試詳解,把答案倒背如流,但是問(wèn)到如何劫持請(qǐng)求的時(shí)候就一臉懵逼,是因?yàn)檫€是停留在理論性階段。前言 在大廠工作了6年,當(dāng)了3年的前端面試官,把大廠常問(wèn)的面試題與答案匯總在我的Github中。希望對(duì)大家有所幫助,助力大家進(jìn)入自己理想的企業(yè)。 項(xiàng)目地址是:git...

    silvertheo 評(píng)論0 收藏0
  • 【周刊-2】三年廠面試官-前端面試題(偏難)

    摘要:前言在大廠工作了年,當(dāng)了年的前端面試官,把大廠常問(wèn)的面試題與答案匯總在我的中。第題如何劫持的請(qǐng)求,提供思路難度阿里騰訊很多人在上搜索前端面試詳解,把答案倒背如流,但是問(wèn)到如何劫持請(qǐng)求的時(shí)候就一臉懵逼,是因?yàn)檫€是停留在理論性階段。 前言 在大廠工作了6年,當(dāng)了3年的前端面試官,把大廠常問(wèn)的面試題與答案匯總在我的Github中。希望對(duì)大家有所幫助,助力大家進(jìn)入自己理想的企業(yè)。 項(xiàng)目地址是:...

    joywek 評(píng)論0 收藏0
  • 【周刊-2】三年廠面試官-前端面試題(偏難)

    摘要:前言在大廠工作了年,當(dāng)了年的前端面試官,把大廠常問(wèn)的面試題與答案匯總在我的中。第題如何劫持的請(qǐng)求,提供思路難度阿里騰訊很多人在上搜索前端面試詳解,把答案倒背如流,但是問(wèn)到如何劫持請(qǐng)求的時(shí)候就一臉懵逼,是因?yàn)檫€是停留在理論性階段。 前言 在大廠工作了6年,當(dāng)了3年的前端面試官,把大廠常問(wèn)的面試題與答案匯總在我的Github中。希望對(duì)大家有所幫助,助力大家進(jìn)入自己理想的企業(yè)。 項(xiàng)目地址是:...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<