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

資訊專欄INFORMATION COLUMN

貓頭鷹的深夜翻譯:從1000+JS項目中匯總的10個最容易出現(xiàn)的錯誤(以及如何解決)

eccozhou / 2421人閱讀

摘要:常出現(xiàn)的錯誤前十位為了可讀性,錯誤名稱進行了一定的簡寫。讓我們深入了解每個錯誤發(fā)生的原因以及解決方法。這個問題很容易解決。當(dāng)未捕獲的錯誤跨越違法跨域策略的域邊界時,會發(fā)生腳本錯誤。這是當(dāng)你在中試圖調(diào)用的方法時出現(xiàn)的錯誤。

JavaScript常出現(xiàn)的錯誤前十位

為了可讀性,錯誤名稱進行了一定的簡寫。讓我們深入了解每個錯誤發(fā)生的原因以及解決方法。

1. Uncaught TypeError: Cannot Read Property

如果你是一名JavaScript開發(fā)人員,你可能已經(jīng)記不清楚多少次看到這個錯誤了。當(dāng)你讀取一個undefined對象的屬性或是調(diào)用其上的方法時,就會出現(xiàn)這個錯誤。你可以再Chrome Console中進行測試。

導(dǎo)致這個問題的原因有許多,最常見的是渲染UI組件時對state不恰當(dāng)?shù)某跏蓟?。讓我們看一個真實APP中可能出現(xiàn)該情況的例子。我們選擇了React,但是這樣的不良初始化也適用于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}
  • )}
); } }

這里要注意兩件重要的事情:

組件的state(比如 this.state)在生命周期開始時為undefined。

當(dāng)你異步獲取數(shù)據(jù)的時候,component會在數(shù)據(jù)加載之前至少渲染一次 - 無論是否在constructor中獲取數(shù)據(jù),都會運行componentWillMount或是componentDidMount。當(dāng)Quiz第一次渲染的時候,this.state.items為undefined。因此,item列表獲得的值為undefined,因此會報錯"Uncaught TypeError: Cannot read property ‘map’ of undefined"。

這個問題很容易解決。最簡單的方法是,在構(gòu)造器里面將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}
  • )}
); } }

這和你的項目中的代碼不一定完全相同,但是我們希望給你提供一個解決或是避免該問題的思路。

2. TypeError: ‘undefined’ Is Not an Object (evaluating...)

這是一個在Safari中在undefined對象上訪問屬性或方法時報的錯。你可以在Safari的控制臺上進行測試。這個錯誤和之前在Chrome中出現(xiàn)的錯誤是相同,只是報錯信息不同。

3. TypeError: Null Is Not an Object (evaluating...)

這是在Safari中在訪問null對象上的屬性或方法時報的錯。

有趣的是,在JavaScript中,null和undefined是不同的,所以我們看到了兩個不同的報錯信息。Undefined通常是指一個尚未賦值的變量,而null是指該變量的值為空。要想判斷二者不等,應(yīng)當(dāng)使用嚴格的相等操作符:

在真實世界中,這種錯誤可能出現(xiàn)的原因之一是你試圖在元素加載完成之前訪問DOM元素。對于空白的對象引用,DOM API會返回null。

任何對DOM元素進行處理的JS代碼都應(yīng)該都在DOM元素創(chuàng)建完成之后進行。JS代碼按照HTML中的規(guī)定按從上到下的順序進行解釋。所以,如果在DOM元素之前存在標(biāo)簽,則腳本標(biāo)簽內(nèi)的JS代碼將在瀏覽器解析HTML頁面時執(zhí)行。如果在加載腳本之前尚未創(chuàng)建相關(guān)的DOM元素,就會出現(xiàn)此錯誤。

在這個例子中,我們通過添加一個事件監(jiān)聽器通知我們頁面已經(jīng)完成加載,來解決這個問題。一旦addEventListener被觸發(fā),init()方法就能夠使用DOM元素。


4. (unknown): Script Error

當(dāng)未捕獲的JavaScript錯誤跨越違法跨域策略的域邊界時,會發(fā)生腳本錯誤。比如,如果你將你的JavaScript代碼托管到CDN上,任何未被捕捉的錯誤(沒有被try-catch塊捕獲,被冒泡至window.onerror處理器的錯誤)將會被簡單的報告為Script Error,不包含任何有用的信息。這是瀏覽器的一種安全措施,旨在防止跨域傳遞數(shù)據(jù)。

要想獲得真正的報錯信息,做以下幾步:

1. 發(fā)送Access-Control-Allow-Origin頭

Access-Control-Allow-Origin設(shè)置為.來標(biāo)記該資源從任何域都可以正常訪問。如果需要的話,也可以將其設(shè)置為自己的域名:比如,Access-Control-Allow-Origin: www.example.com。但是,處理多個域會變的棘手,而且如果你是出于緩存的問題而使用CDN,那么這樣子的代價可能不值得。詳情參考這里

這里給出一些在不同的環(huán)境中設(shè)置header的例子:
Apache
在你存放JavaScript的文件夾中添加一個.htacess文件,包含以下內(nèi)容:

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

Nginx
將add_header指令添加到為JavaScript文件提供服務(wù)的位置塊:

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

HAProxy
將以下內(nèi)容添加到提供JavaScript的asset backend

rspadd Access-Control-Allow-Origin: *
2. 在script標(biāo)簽上設(shè)置crossorigin="annonymous"屬性

在HTML中,對于每一個設(shè)置了Access-Control-Allow-Origin頭的腳本,在腳本的標(biāo)簽上添加crossorigin="anonymous"屬性。在將crossorigin屬性添加到腳本之前,請確保驗證是否為腳本文件設(shè)置了header。在火狐瀏覽器中,如果設(shè)置了crossorigin屬性但是沒有設(shè)置Access-Control-Allow-Origin頭,該腳本不會執(zhí)行。

5. TypeError: Object Doesn’t Support Property

這是在IE瀏覽器中報的錯,當(dāng)你試圖調(diào)用一個undefined對象的方法時:

這等價于Chrome中的TypeError: ‘undefined’ is not a function錯誤。是的,不同的瀏覽器對相同的錯誤會產(chǎn)生不同的報錯信息。

對于使用JavaScript命名空間的Web程序,在IE上運行時經(jīng)常會遇到這個錯誤。當(dāng)這個錯誤出現(xiàn)時,99.9%的情況是因為IE不能將當(dāng)前的命名空間的方法綁定到this關(guān)鍵字上。比如,假設(shè)你有一個JS命名空間Rollbar,其下有一個方法isAwesome()。通常在Rollbar命名空間下你會用如下的語法調(diào)用isAwesome方法:

this.isAwesome();

Chrome,F(xiàn)irfox和Opera都會愉快的接受這個語法。但是,IE并不會。因此,使用JS命名空間時最安全的選擇是始終以實際的命名空間作為前綴。

Rollbar.isAwesome();
6. TypeError: ‘undefined’ Is Not a Function

這是當(dāng)你在Chrome中試圖調(diào)用undefined的方法時出現(xiàn)的錯誤。

隨著JavaScript的編程技巧和設(shè)計模式在這幾年來越來越復(fù)雜,在回調(diào)和閉包中自我引用范圍的擴散也相應(yīng)的增加,導(dǎo)致對this出現(xiàn)困惑。
看下面這段代碼:

function testFunction() {
  this.clearLocalStorage();
  this.timer = setTimeout(function() {
    this.clearBoard();    // what is "this"?
  }, 0);
};

運行上面的代碼會出現(xiàn)"Uncaught TypeError: undefined is not a function."報錯。原因是當(dāng)你試圖調(diào)用setTimeout()方法時,你實際上在調(diào)用window.setTimeout()方法。因此,一個匿名的函數(shù)傳入到setTimeout()方法中,該函數(shù)的上下文實際上是window對象,而window對象沒有clearBoard()方法。

一個傳統(tǒng)的,瀏覽器兼容的方案是將引用this存儲到一個變量中,該引用能夠被閉包繼承,如下:

function testFunction () {
  this.clearLocalStorage();
  var self = this;   // save reference to "this", while it"s still this!
  this.timer = setTimeout(function(){
    self.clearBoard();  
  }, 0);
};

在新版本的瀏覽器中,你可以使用bind()方法來傳遞引用:

function testFunction () {
  this.clearLocalStorage();
  this.timer = setTimeout(this.reset.bind(this), 0);  // bind to "this"
};
function reset(){
    this.clearBoard();    //back in the context of the right "this"!
};
7. Uncaught RangeError: Maximum Call Stack

這是在Chrome中出現(xiàn)的一種錯誤。情況之一是當(dāng)你調(diào)用了一個沒有終止的遞歸方法:

當(dāng)你向方法傳了一個超越規(guī)定范圍的值也可能會出現(xiàn)這個報錯。很多方法只接受特定范圍的值作為輸入。比如,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!
8. TypeError: Cannot Read Property ‘length’

這是在Chrome中讀取一個undefined對象的length屬性時報的錯。

你通??梢栽赼rray中找到length屬性,但是你也可能在array還沒有初始化或是變量名被隱藏在另一個上下文中時遇到這個錯誤。讓我們用下面這個例子理解一下這個報錯:

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

當(dāng)你在方法中聲明參數(shù)時,這些參數(shù)成為了局部變量。這意味著即使你有名為testArray的全局變量,方法中相同名稱的參數(shù)還是會被當(dāng)做局部變量。

你有兩種方法來結(jié)局這個問題:

刪去方法聲明中的參數(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ù)

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

當(dāng)我們試圖訪問一個undefined的變量時,通常會返回undefined,而我們不能獲取或是設(shè)置undefined的屬性。這時候,應(yīng)用就會拋出“Uncaught TypeError cannot set property of undefined.”報錯。

如果test對象不存在,也會拋出“Uncaught TypeError cannot set property of undefined.”。

10. ReferenceError: Event Is Not Defined

當(dāng)你試圖訪問的變量為undifined或是不在當(dāng)前作用域范圍內(nèi)時,會拋出這個錯誤:

如果你在使用事件處理系統(tǒng)時遇到這個報錯,請確保你將事件對象作為參數(shù)傳入了處理方法中。老的瀏覽器器如IE會提供一個全局的事件變量,而Chrome會自動將事件變量附屬到handler上。Firfox不會自動添加它。而類似jQuery之類的庫則試圖規(guī)范化這個行為。總之,你最好將event作為采納數(shù)傳入事件處理方法中:

document.addEventListener("mousemove", function (event) {
  console.log(event);
})
總結(jié)

看來大多數(shù)的錯誤都是null或是undefined相關(guān)的錯誤。如果你在使用編譯器的嚴格模式選項,一個良好的類型檢查系統(tǒng)如Typescript能夠幫助你避免這些問題。它會在一個預(yù)期類型沒有被定義時警告你。即便沒有Typescript, 它也能幫助我們使用防御性編程,在調(diào)用對象之前檢查對象是否是undefined。

我們希望你能夠?qū)W到一些新的內(nèi)容,并且在未來能夠避免這些錯誤,也可能這個指南幫你解決了一些頭疼的問題。無論如何,即便是最佳實踐,在編碼過程中還是會出現(xiàn)意料之外的錯誤。了解影響用戶使用的錯誤并且擁有可以快速解決問題的工具是很重要的。


想要了解更多開發(fā)技術(shù),面試教程以及互聯(lián)網(wǎng)公司內(nèi)推,歡迎關(guān)注我的微信公眾號!將會不定期的發(fā)放福利哦~

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

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

相關(guān)文章

  • 頭鷹深夜翻譯:JAVA中異常處理最佳實踐

    摘要:無需檢查的異常也是的子類。從低層拋出的需檢查異常強制要求調(diào)用方捕獲或是拋出該異常。當(dāng)前執(zhí)行的線程將會停止并報告該異常。單元測試允許我在使用中查看異常,并且作為一個可以被執(zhí)行的文檔來使用。不要捕獲最高層異常繼承的異常同樣是的子類。 前言 異常處理的問題之一是知道何時以及如何去使用它。我會討論一些異常處理的最佳實踐,也會總結(jié)最近在異常處理上的一些爭論。 作為程序員,我們想要寫高質(zhì)量的能夠解...

    W_BinaryTree 評論0 收藏0
  • 頭鷹深夜翻譯:持久化容器存儲

    摘要:如果我們的容器使用,文件如下在這個例子中,我們可以重復(fù)創(chuàng)建和銷毀,同一個持久存儲會被提供給新的,無論容器位于哪個節(jié)點上。 前言 臨時性存儲是容器的一個很大的買點。根據(jù)一個鏡像啟動容器,隨意變更,然后停止變更重啟一個容器。你看,一個全新的文件系統(tǒng)又誕生了。 在docker的語境下: # docker run -it centos [root@d42876f95c6a /]# echo H...

    tianhang 評論0 收藏0
  • 頭鷹深夜翻譯:持久化容器存儲

    摘要:如果我們的容器使用,文件如下在這個例子中,我們可以重復(fù)創(chuàng)建和銷毀,同一個持久存儲會被提供給新的,無論容器位于哪個節(jié)點上。 前言 臨時性存儲是容器的一個很大的買點。根據(jù)一個鏡像啟動容器,隨意變更,然后停止變更重啟一個容器。你看,一個全新的文件系統(tǒng)又誕生了。 在docker的語境下: # docker run -it centos [root@d42876f95c6a /]# echo H...

    xiao7cn 評論0 收藏0
  • 頭鷹深夜翻譯:Volatile原子性, 可見性和有序性

    摘要:有可能一個線程中的動作相對于另一個線程出現(xiàn)亂序。當(dāng)實際輸出取決于線程交錯的結(jié)果時,這種情況被稱為競爭條件。這里的問題在于代碼塊不是原子性的,而且實例的變化對別的線程不可見。這種不能同時在多個線程上執(zhí)行的部分被稱為關(guān)鍵部分。 為什么要額外寫一篇文章來研究volatile呢?是因為這可能是并發(fā)中最令人困惑以及最被誤解的結(jié)構(gòu)。我看過不少解釋volatile的博客,但是大多數(shù)要么不完整,要么難...

    Lionad-Morotar 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<