整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          10 種 JavaScript 最常見的錯誤

          10 種 JavaScript 最常見的錯誤

          看了數千個項目后,發現了 10 個最常見的 JavaScript 錯誤。我們會告訴你什么原因導致了這些錯誤,以及如何防止這些錯誤發生。如果你能夠避免落入這些 “陷阱”,你將會成為一個更好的開發者。

          一、Uncaught TypeError: Cannot read property

          如果你是一個 JavaScript 開發人員,可能你看到這個錯誤的次數比你敢承認的要多。當你讀取一個未定義的對象的屬性或調用其方法時,這個錯誤會在 Chrome 中出現。 您可以很容易的在 Chrome 開發者控制臺中進行測試。

          發生這種情況的原因很多,但常見的一種是在渲染 UI 組件時對于狀態的初始化操作不當。

          我們來看一個在真實應用程序中發生的例子:我們選擇 React,但該情況也同樣適用于 Angular、Vue 或任何其他框架。

          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>
           );
           }
          }
          

          兩個重要的流程:

          1. 組件的狀態(例如 this.state)開始于 undefined。
          2. 當異步獲取數據時,不管它是在構造函數 componentWillMount 還是 componentDidMount 中獲取的,組件在數據加載之前至少會呈現一次,當 Quiz 第一次呈現時,this.state.items 是 undefined。

          這很容易解決。最簡單的方法:在構造函數中初始化 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 (
           <ul>
           {this.state.items.map(item=>
           <li key={item.id}>{item.name}</li>
           )}
           </ul>
           );
           }
          }
          

          在你的應用程序中的具體代碼可能是不同的,但我們希望我們已經給你足夠的線索,以解決或避免在你的應用程序中出現的這個問題。如果還沒有,請繼續閱讀,因為我們將在下面覆蓋更多相關錯誤的示例。

          2、 TypeError: ‘undefined’ is not an object

          這是在 Safari 中讀取屬性或調用未定義對象上的方法時發生的錯誤。您可以在 Safari Developer Console 中輕松測試。這與第一點中提到的 Chrome 的錯誤基本相同,但 Safari 使用了不同的錯誤消息提示語。

          3、 TypeError: null is not an object

          這是在 Safari 中讀取屬性或調用空對象上的方法時發生的錯誤。 您可以在 Safari Developer Console 中輕松測試。

          有趣的是,在 JavaScript 中,null 和 undefined 是并不同,這就是為什么我們看到的是兩個不同的錯誤信息。

          undefined 通常是一個尚未分配的變量,而 null 表示該值為空。 要驗證它們不相等,請嘗試使用嚴格的相等運算符===

          在我們工作中,這種錯誤可能發生的一種場景是:如果在加載元素之前嘗試在 JavaScript 中使用元素。 因為 DOM API 對于空白的對象引用返回值為 null。

          任何執行和處理 DOM 元素的 JS 代碼都應該在創建 DOM 元素之后執行。

          JS 代碼按照 HTML 中的規定從上到下進行解釋。 所以,如果 DOM 元素之前有一個標簽,腳本標簽內的 JS 代碼將在瀏覽器解析 HTML 頁面時執行。 如果在加載腳本之前尚未創建 DOM 元素,則會出現此錯誤。

          在這個例子中,我們可以通過添加一個事件監聽器來解決這個問題,這個監聽器會在頁面準備好的時候通知我們。 一旦 addEventListener 被觸發,init() 方法就可以使用 DOM 元素。

          <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 處理程序引發的錯誤,而不是捕獲在 try-catch 中)被瀏覽器的跨域策略限制時,會產生這類的腳本錯誤。 例如,如果您將您的 JavaScript 代碼托管在 CDN 上,則任何未被捕獲的錯誤將被報告為“腳本錯誤” 而不是包含有用的堆棧信息。這是一種瀏覽器安全措施,旨在防止跨域傳遞數據,否則將不允許進行通信。

          要獲得真正的錯誤消息,請執行以下操作:

          1. 設置 ‘Access-Control-Allow-Origin’ 頭部

          將 Access-Control-Allow-Origin 標頭設置為 * 表示可以從任何域正確訪問資源。

          在 Nginx 中設置如下:

          將 add_header 指令添加到提供 JavaScript 文件的位置塊中:

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

          2. 在 <script> 中設置 crossorigin="anonymous"

          在您的 HTML 代碼中,對于您設置了 Access-Control-Allow-Origin 的每個腳本,在 script 標簽上設置 crossorigin=“anonymous”。在腳本標記中添加 crossorigin 屬性之前,請確保驗證上述 header 正確發送。

          在 Firefox 中,如果存在crossorigin屬性,但Access-Control-Allow-Origin頭不存在,則腳本將不會執行。

          5、 TypeError: Object doesn’t support property

          這是您在調用未定義的方法時發生在 IE 中的錯誤。 您可以在 IE 開發者控制臺中進行測試。

          這相當于 Chrome 中的 “TypeError:”undefined“ is not a function” 錯誤。

          是的,對于相同的邏輯錯誤,不同的瀏覽器可能具有不同的錯誤消息。

          對于使用 JavaScript 命名空間的 Web 應用程序,這是一個 IE 瀏覽器的常見的問題。 在這種情況下,99.9% 的原因是 IE 無法將當前名稱空間內的方法綁定到 this 關鍵字。

          例如:如果你 JS 中有一個命名空間 Rollbar 以及方法 isAwesome。 通常,如果您在 Rollbar 命名空間內,則可以使用以下語法調用 isAwesome 方法:

          this.isAwesome();
          

          Chrome,Firefox 和 Opera 會欣然接受這個語法。 但是 IE 卻不會。 因此,使用 JS 命名空間時最安全的選擇是始終以實際名稱空間作為前綴。

          Rollbar.isAwesome();
          

          6、 TypeError: ‘undefined’ is not a function

          當您調用未定義的函數時,這是 Chrome 中產生的錯誤。 您可以在 Chrome 開發人員控制臺和 Mozilla Firefox 開發人員控制臺中進行測試。

          function clearBoard(){
           alert("Cleared");
          }
          document.addEventListener("click", function(){
           this.clearBoard(); // what is “this” ?
          });
          

          執行上面的代碼會導致以下錯誤:

          “Uncaught TypeError:this.clearBoard is not a function”。

          原因應該是清楚的,即執行上下文不理解導致的指向錯誤。

          7、 Uncaught RangeError

          當你調用一個不終止的遞歸函數就會發生這種錯誤。您可以在 Chrome 開發者控制臺中進行測試。

          此外,如果您將值傳遞給超出范圍的函數,也可能會發生這種情況。

          許多函數只接受其輸入值的特定范圍的數字。 例如:

          1. toExponential(digits) 和 toFixed(digits) 接受 0 到 100
          2. toPrecision(digits) 接受 1 到 100
          var num=2.555555;
          console.log(num.toExponential(4)); //OK
          console.log(num.toExponential(-2)); //range error!
          console.log(num.toFixed(2)); //OK
          console.log(num.toFixed(105)); //range error!
          console.log(num.toPrecision(1)); //OK
          console.log(num.toPrecision(0)); //range error!
          

          8、 TypeError: Cannot read property ‘length’

          這是 Chrome 中發生的錯誤,因為讀取未定義變量的長度屬性。 您可以在 Chrome 開發者控制臺中進行測試。

          您通常會在數組中找到定義的長度,但是如果數組未初始化或者變量在另一個上下文中,則可能會遇到此錯誤。讓我們用下面的例子來理解這個錯誤。

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

          執行以上代碼會報錯:

          Cannot read property 'length' of undefined

          有兩種方法可以解決這個問題:

          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();
          

          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,我們不能獲取或設置任何未定義的屬性。 在這種情況下會將拋出 “Uncaught TypeError: Cannot set property”。

          10. ReferenceError: event is not defined

          當您嘗試訪問未定義的變量或超出當前作用域的變量時,會引發此錯誤。 您可以在 Chrome 瀏覽器中測試。

          如果在使用 event 時遇到此錯誤,請確保使用傳入的事件對象作為參數。像 IE 這樣的舊瀏覽器提供了一個全局變量事件,但并不是所有瀏覽器都支持。

          document.addEventListener("mousemove", function (event) {
           console.log(event);
          })
          

          總結

          我們看到上面的 10 個最常見的錯誤,其實所涉及的知識點并不難。當你認真讀過《你不知道的 JavaScript》上卷后,這些錯誤基本就不會再出現了。當然,歸根結底還是要有扎實的 javascript 基礎,理解底層原理和實現。

          么是JS延遲加載?

          JS延遲加載,也就是等頁面加載完成之后再加載JavaScript文件

          為什么讓JS實現延遲加載?

          js的延遲加載有助于提高頁面的加載速度。

          Js延遲加載的方式有哪些?一般有以下幾種方式:

          ·defer屬性

          ·async屬性

          ·動態創建DOM方式

          ·使用jQuery的getScript方法

          ·使用setTimeout延遲方法

          ·讓JS最后加載

          1、defer屬性

          HTML 4.01為<script>標簽定義了defer屬性。標簽定義了defer屬性元素中設置defer屬性,等于告訴瀏覽器立即下載,但延遲執行標簽定義了defer屬性。

          用途:表明腳本在執行時不會影響頁面的構造。也就是說,腳本會被延遲到整個頁面都解析完畢之后再執行在<script>元素中設置defer屬性,等于告訴瀏覽器立即下載,但延遲執行

          <!DOCTYPE html>
          <html>
          <head>
          	<script src="test1.js" defer="defer"></script>
          	<script src="test2.js" defer="defer"></script>
          </head>
          <body>
          <!--這里放內容-->
          </body>
          </html>

          說明:雖然<script>元素放在了<head>元素中,但包含的腳本將延遲瀏覽器遇到</html>標簽后再執行HTML5規范要求腳本按照它們出現的先后順序執行。在現實當中,延遲腳本并不一定會按照順序執行defer屬性只適用于外部腳本文件。支持HTML5的實現會忽略嵌入腳本設置的defer屬性

          2、async屬性

          HTML5 為<script>標簽定義了async屬性。與defer屬性類似,都用于改變處理腳本的行為。同樣,只適用于外部腳本文件。標簽定義了async屬性。與defer屬性類似,都用于改變處理腳本的行為。同樣,只適用于外部腳本文件。

          目的:不讓頁面等待腳本下載和執行,從而異步加載頁面其他內容。異步腳本一定會在頁面 load 事件前執行。不能保證腳本會按順序執行

          <!DOCTYPE html>
          <html>
          	<head>
          		<script src="test1.js" async></script>
          		<script src="test2.js" async></script>
          	</head>
          <body>
          <!--這里放內容-->
          </body>
          </html>

          async和defer一樣,都不會阻塞其他資源下載,所以不會影響頁面的加載。

          缺點:不能控制加載的順序

          3、動態創建DOM方式

          //這些代碼應被放置在</ body>標簽前(接近HTML文件底部)
          <script type="text/javascript">
          	function downloadJSAtOnload() {
          		varelement=document .createElement("script");
          		element.src="defer.js";
          		document.body.appendChild(element);
          	}
          	if (window. addEventListener)
          		window.addEventListener("load" ,downloadJSAtOnload, false);
          	else if (window.attachEvent)
          		window.attachEvent("onload", downloadJSAtOnload) ;
          	else
          		window. onload=downloadJSAtOnload;
          </script>

          4、使用jQuery的getScript()方法

          $.getScript("outer.js" , function(){	//回調函數,成功獲取文件后執行的函數
          	console.log(“腳本加載完成")
          });

          5、使用setTimeout延遲方法的加載時間延遲加載js代碼,給網頁加載留出更多時間

          <script type="text/javascript" >
          	function A(){
          		$.post("/1ord/1ogin" ,{name:username,pwd:password},function(){
          			alert("Hello");
          		});
          	}
          	$(function (){
          		setTimeout('A()', 1000);	//延遲1秒
          	})
          </script>

          6、讓JS最后加載

          把js外部引入的文件放到頁面底部,來讓js最后引入,從而加快頁面加載速度例如引入外部js腳本文件時,如果放入html的head中,則頁面加載前該js腳本就會被加載入頁面,而放入body中,則會按照頁面從上倒下的加載順序來運行JavaScript的代碼。所以我們可以把js外部引入的文件放到頁面底部,來讓js最后引入,從而加快頁面加載速度。

          上述方法2也會偶爾讓你收到Google頁面速度測試工具的“延遲加載javascript”警告。所以這里的解決方案將是來自Google幫助頁面的推薦方案。

          //這些代碼應被放置在</body>標簽前(接近HTML文件底部)
          
          <script type="text/javascript">
          	function downloadJSAtonload() {
          		var element=document.createElement("script");
          		element.src="defer.js";
          		document.body.appendChild(element);
          	}
          	if (window.addEventListener)
          		window.addEventListener("load", downloadJSAtOnload, false);
          	else if (window.attachEvent )
          		window.attachEvent("onload", downloadJSAtonload);
          	else window.onload=downloadJSAtOnload;
          </script>

          這段代碼意思等到整個文檔加載完后,再加載外部文件“defer.js”。

          使用此段代碼的步驟:

          6.1)復制上面代碼

          6.2)粘貼代碼到HTML的標簽前 (靠近HTML文件底部)

          6.3)修改“defer.js”為你的外部JS文件名

          6.4)確保文件路徑是正確的。例如:如果你僅輸入“defer.js”,那么“defer.js”文件一定與HTML文件在同一文件夾下。

          注意:

          這段代碼直到文檔加載完才會加載指定的外部js文件。因此,不應該把那些頁面正常加載需要依賴的javascript代碼放在這里。而應該將JavaScript代碼分成兩組。一組是因頁面需要而立即加載的javascript代碼,另外一組是在頁面加載后進行操作的javascript代碼(例如添加click事件。

          本已經過原作者 Viduni Wickramarachchi 授權翻譯。

          你是否經歷過JavaScript中的某些值比較沒有得到預期結果的情況?

          看下面的情況:

          即使[]==0結果為真,if[]條件也沒有根據結果執行。有沒有想過為什么會這樣?

          本文主要說明這些值比較的工作原理以及影響它們的因素。在深入解釋之前,大家要熟悉一個概念:類型轉換

          什么是 JavaScript 類型轉換?

          這也稱為類型強制。對于不熟悉此概念的人來說,它只是將值從一種數據類型自動轉換為另一種數據類型。

          看個例子,大家會更清楚明白。

          在此示例中,定義的兩個變量具有兩種類型;字符串和數字。但是,當我們使用 ==(非嚴格比較)進行比較時,結果為true。原因是當我們使用==比較這兩個時,JavaScript 會自動嘗試將String類型轉換為Number類型以產生結果。這是一種強制轉換。

          JavaScript中有多種強制類型。

          • Number conversions
          • String conversions
          • Boolean conversions
          • 對象的類型轉換

          類型強制轉換都是好的嗎?

          在上述情況下,類型轉換沒有害處。但是,在許多情況下,類型強制會導致問題。

          我們看下面例子。

          在這里,JavaScript已將Number類型轉換為String。這與相等比較中發生的情況相反。我們預期的結果是450。但是,我們得到了String輸出。

          現在,我們對類型轉換以及為什么要避免使用類型轉換有了清晰的了解,讓我們看看如何避免類型轉換。這是本文最重要的部分。因此,請坐下來,喝咖啡并集中精力

          如何避免 JavaScript 類型轉換

          1. 對數學運算使用顯式轉換

          如果你需要對用戶輸入或任何其他值使用數學運算,則在執行該運算之前,自己進行一次顯式轉換會更安全。這樣,可以避免任何意外行為。

          2. 使用模板字面值連接字符串,而不是+

          如果需要連接兩個數字,則使用模板文字會更安全。特別是不確定值的類型。

          也可以使用顯式轉換來導出相同的結果。

          3.當比較值時,使用嚴格的比較(===)

          前面我們看到,當使用==時,JavaScript 會執行隱式類型轉換,這會導致不一致的結果。因此,在我們的生產代碼中使用它是不安全的。

          為了得出預期的結果,應該始終使用===進行比較。三等號隱含地表示:

          我可以同時了解變量的值和類型

          因此,如果將數字和字符串與值進行比較,結果將是false,因為它也會考慮變量的類型。

          這是獲得預期一致結果的更安全的方法。

          在JavaScript中,數據類型有兩種變體。

          • 原始值(字符串、數字等)
          • 非原始值(數組、對象)

          到目前為止,我們已經討論了原始數據類型的類型轉換。我提供的第一個示例涉及非原始數據類型,例如數組。

          所有非原始數據類型都有一個名為.toPrimitive()的內置函數。比較非原始值和原始值時,此函數會自動將非原始類型轉換為原始類型。在我們看過的第一個示例中,當使用此函數進行非嚴格比較時,空數組將轉換為空字符串。確切地說,用于執行此轉換的確切函數是toString()。因此,空數組(將轉換為空字符串)等于0

          正如我們前面所看到的,當在if條件中檢查空數組時,將執行條件中的行。但是,如果空數組隱式轉換為0怎么辦?

          這是在單獨的JavaScript條件下進行的: 真值和虛值 。除了true以外,JavaScript 將大部分有值的視為真值,除了少數值。例如,0-0""被視為虛值。由于空數組不被認為是虛值,當在條件中檢查它時,它將作為真值執行。(這里不會發生類型轉換,空數組保留為數組,這是類型轉換不一致的另一個例子。)

          總結

          JavaScript作為一種松散類型語言,執行隱式類型轉換。這會導致不一致和意想不到的結果。因此,我們應該在任何時候都避免這種類型轉換。如果不確定值的類型,可以使用typeof檢查。檢查類型可以讓我們更好地理解應該如何進行轉換。

          ~完,我是刷碗智,我要去刷碗了,骨的白~


          作者:Viduni Wickramarachchi 譯者:前端小智 來源:stackabuse

          原文:https://blog.bitc.io/how-to-avoid-javascript-type-conversions-29e1258f37d8


          主站蜘蛛池模板: 亚洲a∨无码一区二区| 国产一区精品视频| 国产色欲AV一区二区三区| 国产亚洲一区二区手机在线观看 | 精品福利一区二区三区免费视频| 夜夜精品视频一区二区| 国精产品999一区二区三区有限| 人妻久久久一区二区三区| 2014AV天堂无码一区| 国产一区二区三区电影| 亚洲一区二区三区写真 | 色综合视频一区中文字幕| 亚洲AV福利天堂一区二区三| 无码国产精品一区二区免费式芒果 | 精品无码人妻一区二区三区18| 秋霞日韩一区二区三区在线观看 | 国产乱码一区二区三区爽爽爽| 香蕉久久ac一区二区三区| 成人免费观看一区二区| 国产精品美女一区二区三区| 精品熟人妻一区二区三区四区不卡 | 国产精品毛片a∨一区二区三区| 人妻无码一区二区三区AV| 亚洲综合无码AV一区二区 | 精品无码一区二区三区水蜜桃| 日韩在线一区视频| 呦系列视频一区二区三区| 国产精品一区在线播放| 中文乱码人妻系列一区二区| 亚洲AV无码一区二区三区网址| 国产精品无码AV一区二区三区| 中文字幕日韩一区| 视频一区二区在线播放| 国产成人AV一区二区三区无码| 亚洲一区二区精品视频| 伊人色综合网一区二区三区 | 国产伦精品一区二区三区| 日韩人妻精品一区二区三区视频| 国产另类TS人妖一区二区| 亚洲av午夜福利精品一区人妖| 亚洲国产一区在线|