javascript
10个最常见的JS错误
以下是 JavaScript 錯誤 Top 10:?
為了便于閱讀,我們將每個錯誤描述都縮短了。接下來,讓我們深入到每一個錯誤,來確定什么會導(dǎo)致它,以及如何避免創(chuàng)建它。?
1. Uncaught TypeError: Cannot read property?
如果你是一個 JavaScript 開發(fā)人員,可能你看到這個錯誤的次數(shù)比你敢承認的要多(LOL…)。當你讀取一個未定義的對象的屬性或調(diào)用其方法時,這個錯誤會在 Chrome 中出現(xiàn)。 您可以很容易的在 Chrome 開發(fā)者控制臺中進行測試(嘗試)。?
發(fā)生這種情況的原因很多,但常見的一種是在渲染 UI 組件時對于狀態(tài)的初始化操作不當。?
我們來看一個在真實應(yīng)用程序中發(fā)生的例子:我們選擇 React,但該情況也同樣適用于 Angular、Vue 或任何其他框架。?
Javascript代碼?
class?Quiz?extends?Component?{??
??componentWillMount()?{??
????axios.get('/thedata').then(res?=>?{??
??????this.setState({items:?res.data});??
????});??
??}??
??render()?{??
????return?(??
??????<ul>??
????????{this.state.items.map(item?=>??
??????????<li?key={item.id}>{item.name}</li>??
????????)}??
??????</ul>??
????);??
??}??
}??
這里有兩件重要的事情要實現(xiàn):?
組件的狀態(tài)(例如 this.state)從 undefined 開始。
當異步獲取數(shù)據(jù)時,不管它是在構(gòu)造函數(shù)componentWillMount還是componentDidMount中獲取的,組件在數(shù)據(jù)加載之前至少會呈現(xiàn)一次,當 Quiz 第一次呈現(xiàn)時,this.state.items 是未定義的。 這又意味著 ItemList 將 items 定義為 undefined,并且在控制臺中出現(xiàn)錯誤 - “Uncaught TypeError: Cannot read property ‘map’ of undefined”。
這很容易解決。最簡單的方法:在構(gòu)造函數(shù)中用合理的默認值來初始化 state。?
Javascript代碼?
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?(??
??????<ul>??
????????{this.state.items.map(item?=>??
??????????<li?key={item.id}>{item.name}</li>??
????????)}??
??????</ul>??
????);??
??}??
}??
在你的應(yīng)用程序中的具體代碼可能是不同的,但我們希望我們已經(jīng)給你足夠的線索,以解決或避免在你的應(yīng)用程序中出現(xiàn)的這個問題。如果還沒有,請繼續(xù)閱讀,因為我們將在下面覆蓋更多相關(guān)錯誤的示例。?
2. TypeError: ‘undefined’ is not an object?
這是在 Safari 中讀取屬性或調(diào)用未定義對象上的方法時發(fā)生的錯誤。您可以在 Safari Developer Console 中輕松測試。這與 1 中提到的 Chrome 的錯誤基本相同,但 Safari 使用了不同的錯誤消息提示語。?
?
3. TypeError: null is not an object?
這是在 Safari 中讀取屬性或調(diào)用空對象上的方法時發(fā)生的錯誤。 您可以在 Safari Developer Console 中輕松測試。?
?
有趣的是,在 JavaScript 中,null 和 undefined 是不一樣的,這就是為什么我們看到兩個不同的錯誤信息。undefined 通常是一個尚未分配的變量,而 null 表示該值為空。 要驗證它們不相等,請嘗試使用嚴格的相等運算符 ===:?
?
在現(xiàn)實世界的例子中,這種錯誤可能發(fā)生的一種場景是:如果在加載元素之前嘗試在 JavaScript 中使用元素。 因為 DOM API 對于空白的對象引用返回值為 null。?
任何執(zhí)行和處理 DOM 元素的 JS 代碼都應(yīng)該在創(chuàng)建 DOM 元素之后執(zhí)行。 JS 代碼按照 HTML 中的規(guī)定從上到下進行解釋。 所以,如果 DOM 元素之前有一個標簽,腳本標簽內(nèi)的 JS 代碼將在瀏覽器解析 HTML 頁面時執(zhí)行。 如果在加載腳本之前尚未創(chuàng)建 DOM 元素,則會出現(xiàn)此錯誤。?
在這個例子中,我們可以通過添加一個事件監(jiān)聽器來解決這個問題,這個監(jiān)聽器會在頁面準備好的時候通知我們。 一旦 addEventListener被觸發(fā),init() 方法就可以使用 DOM 元素。?
Html代碼?
<script>??
??function?init()?{??
????var?myButton?=?document.getElementById("myButton");??
????var?myTextfield?=?document.getElementById("myTextfield");??
????myButton.onclick?=?function()?{??
??????var?userName?=?myTextfield.value;??
????}??
??}??
??document.addEventListener('readystatechange',?function()?{??
????if?(document.readyState?===?"complete")?{??
??????init();??
????}??
??});??
</script>??
<form>??
??<input?type="text"?id="myTextfield"?placeholder="Type?your?name"?/>??
??<input?type="button"?id="myButton"?value="Go"?/>??
</form>??
4. (unknown): Script error?
當未捕獲的 JavaScript 錯誤(通過window.onerror處理程序引發(fā)的錯誤,而不是捕獲在try-catch中)被瀏覽器的跨域策略限制時,會產(chǎn)生這類的腳本錯誤。 例如,如果您將您的 JavaScript 代碼托管在 CDN 上,則任何未被捕獲的錯誤將被報告為“腳本錯誤” 而不是包含有用的堆棧信息。這是一種瀏覽器安全措施,旨在防止跨域傳遞數(shù)據(jù),否則將不允許進行通信。?
要獲得真正的錯誤消息,請執(zhí)行以下操作:?
1. 發(fā)送 ‘Access-Control-Allow-Origin’ 頭部?
將 Access-Control-Allow-Origin 標頭設(shè)置為 * 表示可以從任何域正確訪問資源。 如有必要,您可以將域替換為您的域:例如,Access-Control-Allow-Origin:www.example.com。 但是,處理多個域會變得棘手,如果你使用 CDN,可能由此產(chǎn)生更多的緩存問題會讓你感覺到這種努力并不值得。 在這里看到更多。?
這里有一些關(guān)于如何在各種環(huán)境中設(shè)置這個頭文件的例子:?
Apache?
在 JavaScript 文件所在的文件夾中,使用以下內(nèi)容創(chuàng)建一個 .htaccess 文件:?
代碼?
Header?add?Access-Control-Allow-Origin?"*"??
Nginx?
將 add_header 指令添加到提供 JavaScript 文件的位置塊中:?
代碼?
location?~?^/assets/?{??
????add_header?Access-Control-Allow-Origin?*;??
}??
HAProxy?
將以下內(nèi)容添加到您為 JavaScript 文件提供資源服務(wù)的后端:?
代碼?
rspadd?Access-Control-Allow-Origin:\?*??
2. 在 <script> 中設(shè)置 crossorigin="anonymous"?
在您的 HTML 代碼中,對于您設(shè)置了Access-Control-Allow-Origin header 的每個腳本,在 script 標簽上設(shè)置crossorigin =“anonymous”。在腳本標記中添加 crossorigin 屬性之前,請確保驗證上述 header 正確發(fā)送。 在 Firefox 中,如果存在crossorigin屬性,但Access-Control-Allow-Origin頭不存在,則腳本將不會執(zhí)行。?
5. TypeError: Object doesn’t support property?
這是您在調(diào)用未定義的方法時發(fā)生在 IE 中的錯誤。 您可以在 IE 開發(fā)者控制臺中進行測試。?
?
這相當于 Chrome 中的 “TypeError:”undefined“ is not a function” 錯誤。 是的,對于相同的邏輯錯誤,不同的瀏覽器可能具有不同的錯誤消息。?
對于使用 JavaScript 命名空間的 Web 應(yīng)用程序,這是一個 IE l瀏覽器的常見的問題。 在這種情況下,99.9% 的原因是 IE 無法將當前名稱空間內(nèi)的方法綁定到 this 關(guān)鍵字。 例如:如果你 JS 中有一個命名空間 Rollbar 以及方法 isAwesome 。 通常,如果您在 Rollbar 命名空間內(nèi),則可以使用以下語法調(diào)用isAwesome方法:?
Javascript代碼?
this.isAwesome();??
Chrome,Firefox 和 Opera 會欣然接受這個語法。 另一方面 IE,不會。 因此,使用 JS 命名空間時最安全的選擇是始終以實際名稱空間作為前綴。?
Javascript代碼?
Rollbar.isAwesome();??
6. TypeError: ‘undefined’ is not a function?
當您調(diào)用未定義的函數(shù)時,這是 Chrome 中產(chǎn)生的錯誤。 您可以在 Chrome 開發(fā)人員控制臺和 Mozilla Firefox 開發(fā)人員控制臺中進行測試。?
?
隨著 JavaScript 編碼技術(shù)和設(shè)計模式在過去幾年中變得越來越復(fù)雜,回調(diào)和關(guān)閉中的自引用范圍也相應(yīng)增加,這是這種/那種混淆的相當常見的來源。?
考慮這個代碼片段:?
Javascript代碼?
function?testFunction()?{??
??this.clearLocalStorage();??
??this.timer?=?setTimeout(function()?{??
????this.clearBoard();????//?what?is?"this"???
??},?0);??
};??
執(zhí)行上面的代碼會導(dǎo)致以下錯誤:“Uncaught TypeError:undefined is not a function”。 你得到上述錯誤的原因是,當你調(diào)用setTimeout()時,實際上是調(diào)用window.setTimeout()。 因此,在窗口對象的上下文中定義了一個傳遞給setTimeout()的匿名函數(shù),該函數(shù)沒有clearBoard()方法。?
一個傳統(tǒng)的,舊瀏覽器兼容的解決方案是簡單地將您的 this 保存在一個變量,然后可以由閉包繼承。 例如:?
Javascript代碼?
function?testFunction?()?{??
??this.clearLocalStorage();??
??var?self?=?this;???//?save?reference?to?'this',?while?it's?still?this!??
??this.timer?=?setTimeout(function(){??
????self.clearBoard();????
??},?0);??
};??
或者,在較新的瀏覽器中,可以使用bind()方法傳遞適當?shù)囊?#xff1a;?
Javascript代碼?
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 在一些情況下會發(fā)生的錯誤。 一個是當你調(diào)用一個不終止的遞歸函數(shù)。您可以在 Chrome 開發(fā)者控制臺中進行測試。?
?
此外,如果您將值傳遞給超出范圍的函數(shù),也可能會發(fā)生這種情況。 許多函數(shù)只接受其輸入值的特定范圍的數(shù)字。 例如:Number.toExponential(digits) 和 Number.toFixed(digits) 接受 0 到 20 的數(shù)字,Number.toPrecision(digits) 接受 1 到 21 的數(shù)字。?
Javascript代碼?
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 中發(fā)生的錯誤,因為讀取未定義變量的長度屬性。 您可以在 Chrome 開發(fā)者控制臺中進行測試。?
?
您通常會在數(shù)組中找到定義的長度,但是如果數(shù)組未初始化或者變量名稱在另一個上下文中隱藏,則可能會遇到此錯誤。讓我們用下面的例子來理解這個錯誤。?
Javascript代碼?
var?testArray?=?["Test"];??
function?testFunction(testArray)?{??
????for?(var?i?=?0;?i?<?testArray.length;?i++)?{??
??????console.log(testArray[i]);??
????}??
}??
testFunction();??
當你用參數(shù)聲明一個函數(shù)時,這些參數(shù)變成了函數(shù)作用域內(nèi)的本地參數(shù)。這意味著即使你函數(shù)外有名為 testArray 的變量,在一個函數(shù)中具有相同名字的參數(shù)也會被視為本地參數(shù)。?
您有兩種方法可以解決您的問題:?
1. 刪除函數(shù)聲明語句中的參數(shù)(事實上你想訪問那些聲明在函數(shù)之外的變量,所以你不需要函數(shù)的參數(shù)):?
Javascript代碼?
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();??
2. 用聲明的數(shù)組調(diào)用該函數(shù):?
Javascript代碼?
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?
當我們嘗試訪問一個未定義的變量時,它總是返回 undefined,我們不能獲取或設(shè)置任何未定義的屬性。 在這種情況下,應(yīng)用程序?qū)伋?“Uncaught TypeError: Cannot set property”。?
例如,在 Chrome 瀏覽器中:?
?
如果測試對象不存在,錯誤將會拋出 “Uncaught TypeErrorUncaught TypeError: Cannot set property”。?
10. ReferenceError: event is not defined?
當您嘗試訪問未定義的變量或超出當前范圍的變量時,會引發(fā)此錯誤。 您可以在 Chrome 瀏覽器中輕松測試。?
?
如果在使用事件處理系統(tǒng)時遇到此錯誤,請確保使用傳入的事件對象作為參數(shù)。像 IE 這樣的舊瀏覽器提供了一個全局變量事件,但并不是所有瀏覽器都支持。像 jQuery 這樣的庫試圖規(guī)范化這種行為。盡管如此,最好使用傳入事件處理函數(shù)的函數(shù)。?
Javascript代碼?
function?myFunction(event)?{??
????event?=?event.which?||?event.keyCode;??
????if(event.keyCode===13){??
???????alert(event.keyCode);??
????}??
}??
總結(jié)
以上是生活随笔為你收集整理的10个最常见的JS错误的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华硕笔记本触摸鼠标手势无效怎么办
- 下一篇: mysql整理类型_MYSQL数据类型分