1. 程式人生 > >javascript程式設計容易出現的11個錯誤

javascript程式設計容易出現的11個錯誤

javascript是比較容易學的。但是,對於這門語言需要有一些值得注意的地方。本文將指出javascript程式設計中可能犯過的10個錯誤

錯誤1-使用全域性變數

如果你剛開始javascript程式設計,可能會覺得全域性變數很好用。事實上,剛開始javascript程式設計,你可能不知道使用全域性變數會帶來什麼麻煩。在同一個頁面中,全域性變數可以在任何內嵌的javascript程式碼段中或是該頁面載入的不同的js檔案中,都能訪問到。這聽起來很強大,是嗎?這就使得全域性變數可以隨時隨地的被修改賦值。
事實上這樣很糟!
這樣做會導致變數在意料之外被修改重寫。假設有一個網店,需要用javascript計算並顯示購物車所有商品的價格總和(當然,伺服器端還會進行重新計算,這裡只是為了增強使用者的體驗)。可能會編寫程式碼如下:

  1. vartotal = 0// total price
  2. tax = 0.05// 5%

現在,還需要用javascript程式碼在網站上展示一些資訊,或則是做一個商品倉庫。程式碼如下:

  1. vartotal = 15// number of tweets pulled from twitter

或則是如下程式碼:

  1. vartax = function(){/* ... */}// Trigger Animation eXperience function

現在,出現問題了:兩個重要的變數被重寫,但可能還沒被意識到。這樣程式碼執行會出錯,會花費很多時間來跟蹤和修復該錯誤。
那該如何解決呢?簡言之—“封裝”:當然封裝有很多方法可以實現。第一種做法是將程式碼放入一個匿名的自調函式中。程式碼如下:

  1. (function(){
  2. vartotal = 0tax = 0.05;
  3. // other code
  4. }());

這樣做,在函式外部是絕對不能訪問到函式內部定義的變數。這就形成了個人的程式碼空間,但是這樣就不能公開部分方法或屬性。例如,想要建立一個購物車,定義一個總價的變數,作為公共屬性,這種情形下可以採用模組式程式設計。

  1. varcartTotaler = (function(){
  2. vartotal = 0tax = 0.05;
  3. // other code
  4. return{
  5. addItem : function(item){},
  6. removeItem : function(item){},
  7. calculateTitle
     : function(){}
  8. };
  9. }());

關於全域性變數有一點值得注意,如果不用關鍵詞var來宣告建立變數,那麼javascript引擎會預設將該變數定義為全域性變數。

  1. (function(){
  2. tax = 0.05;
  3. }());
  4. vartotalPrice = 100 + (100 * tax)// 105

這裡的變數tax在函式外部也是可以被訪問的,因為在定義tax的時候沒有使用var關鍵詞。

錯誤2-不加分號

每句javascript語句必須以分號結尾。在程式設計時如果忘了加分號,這時javascript編解析器會自動加上。那我們在程式設計的時候是不是就可以完全不用浪費時間去加分號呢?
但是在一些語句中,分號是必不可少的。如for迴圈語句中的分號是必不可少的,否則會報語法錯誤。那麼語句末尾的分號呢?
Javascript社群已經討論過該問題。下面是本文的看法:你的程式碼,只要是被javascript解析器修改過(即便是很小的修改,如新增分號),就可能會出現一些你意料之外的結果。看看下面這段javascript程式碼:

  1. functionreturnPerson(name){
  2. return
  3. {
  4. name : name
  5. };
  6. }

該方法看起來會返回一個物件,但事實上,javascript解析器會在return後面緊接著新增一個分號,這就導致該函式返回undefined。Return後的物件會被忽略。解決方法很簡單,程式碼如下:

  1. return{
  2. name : name
  3. };

在javascript程式設計中應嚴格要求自己新增分號,這個習慣並不難。當然,作為一名web開發人員,你可能也會用到其他的語言(如php),這些語言都是嚴格要求以分號結尾的。你可以把這些程式語言的習慣帶到javascript程式設計中來。
作者註解:除了你完全肯定可以被忽略的地方,你都不可以忽略新增分號。

錯誤3-使用==

如果你問一個javascript程式設計者,在javascript程式設計中通常會犯什麼錯誤。他/她很可能會說,使用= = =來代替= =。這是什麼意思呢?
試試下面的程式碼:

  1. if(1 == 1){
  2. console.log("it's true!");
  3. }

程式碼如你所願的輸出了“it’s true!”那再試試下面的程式碼:

  1. if(1 == '1'){
  2. console.log("it's true!");
  3. }

這段程式碼在控制檯中盡然也輸出了“it’s true!”,但其實這並不是你所期望的輸出。這裡的==運算子轉換了運算數的型別,從而使得兩個運算數相等了。這裡if語句中的==運算子使得右邊string型別的“1”變成了number型的1。
想要得到你想要的輸出,這裡應該用= = =運算子來代替= =。===不會強制轉換運算數的型別,這樣才能如你所期望的。同樣地,用!= =運算子來替換!=。下面是用==來做比較,得出的結果令人意外。

  1. '' == '0'// false
  2. '0' == ''// true
  3. false == '0'// true
  4. ' \t\r\n ' == 0// true

錯誤4-使用資料型別的包裝物件

Javascript提供了各個資料型別的包裝物件。

  1. newNumber(10);
  2. newString("hello");
  3. newBoolean(true);
  4. newObject();
  5. newArray("one""two""three");

首先,它們並不好用。上面的程式碼可以用更少的程式碼來實現,如下:

  1. 10;
  2. "hello";
  3. true;
  4. {};
  5. ["one""two""three"];

但是這兩種方式還是有所不同的。下面是douglas crockford的觀點:
例如用new Boolean(false)建立一個物件,該物件有一個方法valueOf,呼叫該方法會返回構造器的值。
這意味著,如果執行typeof new Number(10)或者是typeof new String(‘hello’),將返回‘object’,而不是’number’或’string’.另外,用資料型別的包裝還會引發一些意料之外的結果。
那麼為什麼javascript要提供資料型別的包裝物件呢?這是因為javascript解析器內部會呼叫。簡單的資料型別是沒有方法的(因為它們不是物件),所以當呼叫簡單型別的資料的方法時(如’hello’.replace(‘ello’, ‘i’)),javascript會呼叫String包裝物件來建立一個臨時的string物件,然後呼叫該物件的方法,完成呼叫後會刪除這個臨時物件。
所以不要用資料型別的包裝物件來建立簡單型別的資料。
注意:本來不用這麼說明的,但本文還是想明確的告訴初學者:不是說不使用它們和new(儘管有些是推薦使用的),這裡需要特別指出的是,這個建議特別針對這些資料型別,如:number、string、Boolean、array和空物件。

錯誤5-在使用for-in時不對屬性檢查

我們都很熟悉遍歷陣列,但是你可能還希望能遍歷物件的屬性。(題外話:array事實上是屬性名為數字的物件)。這是可以用for-in迴圈語句,程式碼如下:

  1. varpropobj = {name"Joe"job"Coder"age25};
  2. for(varpropinobj){
  3. console.log(prop + "" + obj[prop]);
  4. }

執行上面的程式碼,輸出如下:

  1. nameJoe
  2. jobCoder
  3. age25

但是,瀏覽器中for-in遍歷物件屬性和方法時會包括物件原型鏈上的所有屬性和方法。但絕大多數屬性是不希望被枚舉出來的。可以用hasOwnProperties方法來檢測屬性是否屬於物件。程式碼如下:

  1. FunctionDog(name){
  2. this.name = name;
  3. }
  4. Dog.prototype.legs = 4;
  5. Dog.prototype.speak = function(){
  6. return"woof!";
  7. };
  8. vard = newDog("Bowser");
  9. for(varpropind){
  10. console.log(prop + "" + d[prop]);
  11. }
  12. console.log("=====");
  13. for(varpropind){
  14. if(d.hasOwnProperty(prop)){
  15. console.log(prop + "" + d[prop]);
  16. }
  17. }
  18. // Output
  19. // name: Bowser
  20. // legs: 4
  21. // speak: function () {
  22. return"woof!";
  23. // }
  24. // =====
  25. // name: Bowser

有時,只希望列舉列出物件的的屬性,不包括方法。可以用typeof方法,程式碼如下:

  1. for(varpropind){
  2. if(typeofd[prop] !== 'function'){
  3. console.log(prop + "" + d[prop]);
  4. }
  5. }

不管怎麼樣,在用for-in迴圈時要確保對屬性進行檢測,以避免得到你意料之外的結果。

錯誤6-使用with或eval

幸運的是,現在大部分javascript教程都不會教你使用with或eval。但是一些老教程或名氣不大的資料時(因為有時候好的資料在網上很難找到),可能會發現有使用with或eval。
下面是兩個不用with的主要原因:
1、 它會降低程式碼效能
2、 不易於程式碼閱讀

第一點是它與生俱來的。第二點,看看下面的程式碼,這裡用with訪問person物件的name、age屬性。

  1. varperson = {name"Joe"age : 10};
  2. with(person){
  3. console.log(name)// Joe
  4. console.log(age)// 10
  5. }

但是,若果有一個變數和物件其中一個屬性同名,那用with會發生什麼呢?事實上,這種情況下,訪問變數會引用那個變數而不是物件的屬性。另一個值得注意的是,在with語句中,如果訪問的屬性不存在或物件不存在,就不能給物件新增屬性,同時會使得作用域鏈上with作用域後的那個作用域中建立一個變數。

  1. varperson = {name"Joe"age : 10},
  2. name = "Billy";
  3. with(person){
  4. console.log(name)// Billy
  5. job = "Designer";
  6. }
  7. console.log(person.job)// undefined;
  8. console.log(job)// Designer

那eval呢?它可以接受一個字串引數,並且解析執行改字串。

這聽起來沒有什麼不好,甚至覺得很棒,對嗎?但問題就是這太棒了!與其將一連串字串將給它來解析執行,為什麼不直接編寫在程式中呢?不該這麼做的原因如下:

  1. 完全可以直接編寫在程式碼中。
  2. eval解析很慢的,效能跟with差不多。

eval的用法是在非執行時執行環境。可以從伺服器端或客戶端獲取程式碼。難道真的想你的網站使用者來底控制你的程式碼?這樣不就意味著你的網站向無數的黑客敞開了大門。用eval就好比,離開了家,並告訴大家鑰匙就是門口墊子下面。如果你愛自己或你的使用者,就不要用eval。

錯誤7-在用parseInt時不用基數

Javascript提供了一個非常有用的方法parseInt,它可以將字串轉換為數值。

  1. parseInt("200")// 200
  2. parseInt("043")// 35

結果是不是令人覺得意外?第二句為什麼不是43?事實上,parseInt方法不僅僅是隻能把字串當做十進位制數來轉換。當parseInt的第一個引數是以0開頭,它就會把字串當作是八進位制數來轉換。這就是不使用基數出現的意料之外結果。第二個引數–基數,會指定parseInt方法把字串當做什麼進位制的數來轉換。(當然,它的返回值永遠是十進位制數)

  1. parseInt("020"10)// 20
  2. parseInt("100"2)// 4

錯誤8 if和while語句不使用{}

Javascript最明顯的特點是語法要求不那麼嚴格。但正是這樣的特點,有時會帶來麻煩。If和while語句的{}就會引起一些麻煩。{}是根據if條件成立時執行程式碼語句的條數來用的。

  1. if(true)
  2. console.log("inside the if statement");

這裡看起來沒什麼問題,因為這裡的執行語句只有一句

  1. vararr = ["one""two""three""four""five""six""seven""eight""nine""ten"],
  2. i = arr.length - i;
  3. while(i)console.log(arr[i--]);

但是這樣做不易於閱讀:首先,不用{}程式碼結構看起來不是那麼清晰。

  1. if(true)
  2. console.log("inside the if-statement.");
  3. console.log("outside the if-statement.");

看看上面的程式碼,第二行console語句是不屬於if執行語句的,但是這裡它看起來像是if的執行語句。使用{}會使結構更清晰。同時,如果你想在if的執行程式碼中新增一句,也需要使用{}。習慣使用{}並不是一件難事。

錯誤9-單個單個地插入dom元素

這並不是javascript自身的問題。99%100的javascript程式設計都會涉及DOM操作,在對DOM操作上會犯很多錯誤,但這是最明顯的一個。
DOM操作會使瀏覽器重繪頁面,所以如果有一連串的元素一個接一個的插入頁面中,這會急劇增加瀏覽器渲染頁面的負擔。

  1. varlist = document.getElementById("list"),
  2. items = ["one""two""three""four"],
  3. el;
  4. for(vari = 0items[i]i++){
  5. 相關推薦

    javascript程式設計容易出現11錯誤

    javascript是比較容易學的。但是,對於這門語言需要有一些值得注意的地方。本文將指出javascript程式設計中可能犯過的10個錯誤 錯誤1-使用全域性變數 如果你剛開始javascript程式設計,可能會覺得全域性變數很好用。事實上,剛開始javascri

    JAVA中容易出現的編譯錯誤解決方式

    1、錯誤顯示:如果請求時出現java.lang.ClassNotFoundException錯誤,如下: j 解決方式如下:1、第一步,去web.xml中檢視  <servlet-class>是否正確  <servlet>   <servl

    提高程式設計技能的11建議

    本文是html5tricks原創翻譯,轉載請看清文末的轉載要求,謝謝合作! 1.首先仔細分析問題 2.接著好好想想如何解決這個問題 3.收集整理所有需求。 花點時間將最終產品要實現的目標寫下來,並且明確哪些是我們的目標使用者群。如果這一步能做好的話,將會給後面節

    JavaScript 初學者容易犯的幾錯誤,你中招沒?

    JavaScript 是對初學者比較友好的一門程式語言,基本上花個半小時看下語法就能寫出能執行的程式碼。JavaScript 是動態指令碼語言,對資料型別沒有太多的限制,寫起來非常靈活。但正因為如此,初學者如果不深入瞭解語言本身,往往會犯一些錯誤,從而導致一些很難發現的 bug。 拋開 JavaScript

    小白學PYTHON時最容易犯的6錯誤,看看你遇到過幾

    逗號 ice fault sep mpat 解釋器 github上 arw 別人 最近又在跟之前的同學一起學習python,一起進步,發現很多測試同學在初學python的時候很容易犯一些錯誤,特意總結了一下。其實這些錯誤不僅是在學python時會碰到,在學習其他語言的時候也

    【已解決】在 Visual Studio 中設置 JavaScript/TypeScript 的斷點 腳本出現自動中斷錯誤

    chrome alt 啟動應用 出現 ont ash 解決方法 腳本調試 設置 運行ASP.NET Core 程序出現錯誤如下: 已啟用 Visual Studio 中的 Chrome 腳本調試 在 Visual Studio 中設置 JavaScript/Type

    4錯誤使用JavaScript數組方法的案例

    布爾 註意 and node.js 金山 getc eric some rip 譯者按: 做一個有追求的工程師,代碼不是隨便寫的! 原文: Here’s how you can make better use of JavaScript arrays 譯者: Fundeb

    【爬坑】Python 3.6 在 Socket 程式設計出現型別錯誤 TypeError: a bytes-like object is required, not 'str'

      1. 問題描述   Python 3.6 在 Socket 程式設計時出現錯誤如下 Traceback (most recent call last): File "F:/share/IdeaProjects/test/mypython/test/test10_tcpcli

    Java 語言最容易出現常見錯誤

    好記憶不如爛筆頭,能夠記錄點什麼,就趕緊記錄點 , 方便知識的積累 !  1. 使用"=="判斷兩個字串相等;     在判斷兩個字串的時候,不要使用"=="判斷兩個字串相等. 2. 在foreach中改變list的結構; &nbs

    Python 初學者最容易犯的幾錯誤

    對於新手,初學Python時,總會遇到這樣那樣的報錯,想要弄懂Python錯誤資訊的含義可能還不知道怎麼做,這裡列出了一些比較常見的Python報錯問題,希望對於學習Python的人能夠有些幫助。 1)嘗試連線非字串值與字串(導致 “TypeError: Can’t con

    nginx比apache處理靜態檔案速度快,但是nginx處理大量併發的php請求時,容易出現502錯誤,頻率大概是多少

    首先要明確一點的是502是怎麼出現的,為什麼會出現502呢?一般而言,出現502的錯誤是因為php-cgi連線數不夠導致的。舉個例子:php-cgi開10個程序,前端發20個請求,每個請求的指令碼都sleep100s,那麼必然有至多10個請求會出現502錯誤。因此,出現502是因為php程序不夠用了,和ngi

    用 Python 程式設計時要避免的 3 錯誤

    這些錯誤會造成很麻煩的問題,需要數小時才能解決。 當你做錯事時,承認錯誤並不是一件容易的事,但是犯錯是任何學習過程中的一部分,無論是學習走路,還是學習一種新的程式語言都是這樣,比如學習 Python。 為了讓初學 Python 的程式設計師避免犯同

    pip 安裝matplotlib2.x版本以及pip出現的兩錯誤

    01安裝matplotlib  今天給python2安裝matplotlib,發現最新的matplotlib版本3.0不再支援python2了,所以需要指定版本號安裝,但是我又不想去查 matplotlib2.x最新版本是多少,於是就使用上pip的指定版本的功能了 sudo pip

    阿里P7總結:JavaScript面試頻繁出現的幾易錯點

    一 前言 這段時間,金三銀四,很多人面試,很多人分享面試題。在前段時間,我也臨時擔任面試官,為了大概瞭解面試者的水平,我也寫了一份題目,面試了幾個前端開發者。在這段時間裡面,我在學,在寫設計模式的一些知識,想不到的設計模式的這些知識,就是面試題裡面,頻繁讓人掉坑的考點。所以,今天就總結一下,那些

    Java程式設計師容易犯的10錯誤

    Array 轉 ArrayList 一般開發者喜歡用: List list = Arrays.asList(arr); Arrays.asList() 會返回一個ArrayList,這是Arrays裡內嵌的一個私有靜態類,而並不是java.util.Arra

    11 超酷的程式設計新工具

    工具對開發人員來說至關重要。工具可以讓一個開發人員的日常工作更高效,並且只需要關注最重要的事情。對於開發人員來講,尋找更好的替代工具往往比堅持使用熟悉單身過時的工具更困難。 在這篇文章中,我們將列出你在日常工作中能夠使用的新的開發工具。很多對線上流媒體感興趣的開發人

    hadoop安裝時容易出現錯誤

    1.設定主機名錯誤 看日誌,會發現下面的錯誤 這是由於主機名設定錯誤造成的,請檢查配置檔案中關於主機名的設定,是否正確。 首先使用 hostname 命令檢視主機名是否正確; 然後使用 more /etc/sysconfig/network 命令檢視主機名是否記錄在檔案中;

    Android studio程式設計出現錯誤:unspecified on project app resolves to an APK archive which is not supported

    用Android Studio中匯入第三方庫工程的時候出現的問題: Error:Dependency MyApplication.libraries:MaterialDesign:unspecified on project app resolves to an APK arch

    android studio程式設計出現錯誤:Error:Execution failed for task ':app:buildInfoDebugLoader'. > Exception whi

    用Android Studio中設定navigation的menu時候出現的問題:(其他問題同理) Error:Execution failed for task ':app:buildInfoDebugLoader'. >  Exception while doing pa

    minibufexplorer導致gvim出現視窗的錯誤

    在gvim下縱向切割視窗,buffer間切換時,minibufexplorer會出現多個檔案標籤視窗。 百度一番發現這篇部落格, 在vimrc中新增 let g:miniBufExplorerMoreThanOne=0 source % 之後沒有生效