在今天,JavaScript已經成為了網頁編輯的核心。尤其是過去的幾年,互聯網見證了在SPA開發、圖形處理、交互等方面大量JS庫的出現。下面電腦知識吧的小編就簡單分享JavaScript中易犯的小錯誤希望可以幫助到大家
如果初次打交道,很多人會覺得js很簡單。確實,對於很多有經驗的工程師,或者甚至是初學者而言,實現基本的js功能幾乎毫無障礙。但是JS的真實功能卻比很多人想象的要更加多樣、復雜。JavaScript的許多細節規定會讓你的網頁出現很多意想不到的bug,搞懂這些bug,對於成為一位有經驗的JS開發者很重要。
我曾經聽一位喜劇演員說過:
“我從未在這裡,因為我不清楚這裡是哪裡,是除了那裡之外的地方嗎?”
這句話或多或少地暗喻了在js開發中開發者對於this關鍵字的使用誤區。This指代的是什麼?它和日常英語口語中的this是一個意思嗎?
隨著近些年js編程不斷地復雜化,功能多樣化,對於一個程序結構的內部指引、引用也逐漸變多起來
下面讓我們一起來看這一段代碼:
Game.prototype.restart = function () { this.clearLocalStorage(); this.timer = setTimeout(function(){ this.clearBoard(); }, 0); };
運行上面的代碼將會出現如下錯誤:
Uncaught TypeError: undefined is not a function
這是為什麼?this的調用和它所在的環境密切相關。之所以會出現上面的錯誤,是因為當你在調用 setTimeout()函數的時候, 你實際調用的是window.setTimeout(). 因此,在 setTimeout() 定義的函數其實是在window背景下定義的,而window中並沒有 clearBoard() 這個函數方法。
下面提供兩種解決方案。第一種比較簡單直接的方法便是,把this存儲到一個變量當中,這樣他就可以在不同的環境背景中被繼承下來:
Game.prototype.restart = function () { this.clearLocalStorage(); var self = this; this.timer = setTimeout(function(){ self.clearBoard();}, 0); };
第二種方法便是用bind()的方法,不過這個相比上一種要復雜一些,對於不熟悉bind()的同學可以在微軟官方查看它的使用方法:https://msdn.microsoft.com/zh-cn/library/ff841995
Game.prototype.restart = function () { this.clearLocalStorage(); this.timer = setTimeout(this.reset.bind(this), 0); }; Game.prototype.reset = function(){ this.clearBoard();};
上面的例子中,兩個this均指代的是Game.prototype。
另一種易犯的錯誤,便是帶著其他編程語言的思維,認為在JS中,也存在生命周期這麼一說。請看下面的代碼:
for (var i = 0; i < 10; i++) { /* ... */ } console.log(i);
如果你認為在運行console.log() 時肯定會報出 undefined 錯誤,那麼你就大錯特錯了。我會告訴你其實它會返回 10嗎。
當然,在許多其他語言當中,遇到這樣的代碼,肯定會報錯。因為i明顯已經超越了它的生命周期。在for中定義的變量在循環結束後,它的生命也就結束了。但是在js中,i的生命還會繼續。這種現象叫做 variable hoisting。
而如果我們想要實現和其他語言一樣的在特定邏輯模塊中具有生命周期的變量,可以用let關鍵字。
內存洩露在js變成中幾乎是一個無法避免的問題。如果不是特別細心的話,在最後的檢查過程中,肯定會出現各種內存洩露問題。下面我們就來舉例說明一下:
var theThing = null; var replaceThing = function () { var priorThing = theThing; var unused = function () { if (priorThing) { console.log("hi"); } }; theThing = { longStr: new Array(1000000).join('*'), // someMethod: function () { console.log