JavaScript >> Javascript 文檔 >  >> JavaScript

JavaScript 初學者常犯的 10 個錯誤

JavaScript 是一門容易上手的語言,但要達到精通則需要付出很多努力。初學者經常犯一些眾所周知的錯誤,這些錯誤會在他們最意想不到的時候捲土重來。要找出這些錯誤,請繼續閱讀!

1。缺少花括號

JavaScript 初學者經常犯的一種做法是在像 if 這樣的語句之後省略花括號 , else , whilefor .儘管允許,但您應該格外小心,因為這種做法通常會隱藏問題並成為錯誤的根源。請看下面的例子:

// Say hello to Gandalf
hello('Gandalf');

function hello(name){

    // This code doesn't do what the indentation implies!

    if(name === undefined)
        console.log('Please enter a username!');
        fail();

    // The following line is never reached:

    success(name);
}

function success(name){
    console.log('Hello, ' + name + '!');
}

function fail(){
    throw new Error("Name is missing. Can't say hello!");
}

雖然 fail() call 是縮進的,看起來好像屬於 if 聲明,它沒有。它總是被調用。因此,始終用花括號括住代碼塊是一種很好的做法,即使只涉及一條語句。

2。缺少分號

在解析 JavaScript 時,有一個稱為自動分號插入的過程。顧名思義,解析器很樂意為您插入缺少的分號。此功能的目的是使 JavaScript 更容易上手,並且更容易被初學者編寫。但是,您應該始終包含分號,因為省略它們存在危險。這是一個例子:

// This code results in a type error. Adding semicolons will fix it.

console.log('Welcome the fellowship!')

['Frodo', 'Gandalf', 'Legolas', 'Gimli'].forEach(function(name){
    hello(name)
})

function hello(name){
    console.log('Hello, ' + name + '!')
}

因為第 3 行缺少分號,解析器假定第 5 行的左括號是嘗試使用數組訪問器語法訪問屬性(請參閱錯誤 #8),而不是單獨的數組,這不是意圖並導致類型錯誤。解決方法很簡單——總是寫分號。

一些經驗豐富的 JavaScript 開發人員喜歡省略分號,但他們非常清楚這可能導致的錯誤並知道如何防止它們。

3。不理解類型強制

JavaScript 是動態類型的。這意味著你在聲明一個新變量時不需要指定類型,你可以自由地重新賦值或轉換它的值。這使得 JavaScript 比 C# 或 Java 更容易編寫,但是您為其他語言在編譯步驟中捕獲的潛在錯誤打開了大門。這是一個例子:

// Listen for the input event on the textbox

var textBox = document.querySelector('input');

textBox.addEventListener('input', function(){

    // textBox.value holds a string. Adding 10 appends 
    // the string '10', it doesn't perform an addition..

    console.log(textBox.value + ' + 10 = ' + (textBox.value + 10));

});
<input type="number" placeholder="Enter a number here" />

使用 parseInt(textBox.value, 10) 可以輕鬆解決此問題 在將字符串加 10 之前將其轉換為數字。根據您使用變量的方式,運行時可能會決定將其轉換為一種或另一種類型。這稱為類型強制。在if中比較變量時防止類型被隱式轉換 語句,您可以使用嚴格的相等檢查 (===)。

4。忘記變量

初學者犯的另一種做法是忘記使用 var 聲明變量時的關鍵字。 JavaScript 非常寬鬆,第一次看到你使用了沒有 var 的變量 聲明,它將在全球範圍內默默地為您聲明。這可能是細微錯誤的來源。這是一個示例,它還顯示了一個不同的錯誤 - 一次聲明多個變量時缺少逗號:

var a = 1, b = 2, c = 3;

function alphabet(str){
    var a = 'A', b = 'B'    // Oops, missing ',' here!
        c = 'C', d = 'D';

    return str + ' ' + a + b + c + '…';
}

console.log( alphabet("Let's say the alphabet!") );

// Oh no! Something went wrong! c has a new value!
console.log(a, b, c);

當解析器到達第 4 行時,它會自動插入一個分號,然後解釋 cd 第 5 行的聲明為全局。這將導致外部 c 變量的值發生變化。在此處閱讀更多 JavaScript 陷阱。

5。帶浮點數的算術運算

這個錯誤幾乎適用於所有的編程語言,包括 JavaScript。由於浮點數在內存中的表示方式,算術運算並不像您想像的那麼精確。這是一個例子:

var a = 0.1, b = 0.2;

// Surprise! this is false:
console.log(a + b == 0.3);

// Because 0.1 + 0.2 does not produce the number that you expect:
console.log('0.1 + 0.2 = ', a + b);

要解決此問題,如果您需要絕對正確性,則不應使用小數 - 使用整數,或者如果您需要處理金錢,請使用 bignumber.js 之類的庫。

6。在文字上使用構造函數

當 Java 和 C# 程序員開始編寫 JavaScript 時,他們通常更喜歡使用構造函數來創建對象:new Array() , new Object() , new String() .儘管它們得到了完美的支持,但建議使用文字符號:[] , {} , "" ,因為構造函數有微妙的特殊性:

/* Using array constructors is valid, but not recommended. Here is why. */

// Create an array with four elements:

var elem4 = new Array(1,2,3,4);

console.log('Four element array: ' + elem4.length);

// Create an array with one element. It doesn't do what you think it does:

var elem1 = new Array(23);

console.log('One element array? ' + elem1.length);

/* String objects also have their warts */

var str1 = new String('JavaScript'),
    str2 = "JavaScript";

// Strict equality breaks:

console.log("Is str1 the same as str2?", str1 === str2);

解決方案很簡單:嘗試始終使用文字符號。另外,JS 數組不需要提前知道自己的長度。

7。不了解作用域的工作原理

初學者很難理解的一個概念是 JavaScript 的作用域規則和閉包。理所當然的:

// Print the numbers from 1 to 10, 100ms apart. Or not.

for(var i = 0; i < 10; i++){
    setTimeout(function(){
        console.log(i+1);
    }, 100*i);
}

/* To fix the bug, wrap the code in a self-executing function expression:

for(var i = 0; i < 10; i++){

    (function(i){
        setTimeout(function(){
            console.log(i+1);
        }, 100*i);
    })(i);

}               

*/

函數保留對其父範圍內變量的可見性。但是因為我們使用 setTimeout 來延遲執行 ,當函數真正運行時,循環已經完成,i 變量遞增到 11。

註釋中的自執行功能有效,因為它複製了 i 按值變量,並為每個超時函數保留一個私有副本。在此處和此處閱讀有關範圍的更多信息。

8。使用評估

評估是邪惡的。這被認為是一種不好的做法,並且在大多數情況下,當您使用它時,會有更好更快的方法。

/* Using eval to access properties dynamically */

var obj = {
    name: 'Foo Barski',
    age: 30,
    profession: 'Programmer'
};

// Which property to access?
var access = 'profession';

// This is a bad practice. Please don't do it:
console.log( eval('obj.name + " is a " + obj.' + access) );

// Instead, use array notation to access properties dynamically:
console.log( obj.name + " is a " + obj[access]);

/* Using eval in setTimout */

// Also bad practice. It is slow and difficult to read and debug:
setTimeout(' if(obj.age == 30) console.log("This is eval-ed code, " + obj[access] + "!");', 100);

// This is better:
setTimeout(function(){

    if(obj.age == 30){
        console.log('This code is not eval-ed, ' + obj[access] + '!');
    }

}, 100);

eval 內的代碼 是一個字符串。由 eval 塊產生的調試消息是難以理解的,您必須處理轉義單引號和雙引號。更不用說它比普通的 JavaScript 慢。除非你知道自己在做什麼,否則不要使用 eval。

9。不懂異步代碼

JavaScript 的獨特之處在於幾乎所有內容都是異步的,您需要傳遞回調函數才能獲得事件通知。這對初學者來說並不直觀,他們很快就會發現自己在一個難以理解的錯誤上摸不著頭腦。這是一個示例,其中我使用 FreeGeoIP 服務通過 IP 獲取您的位置:

var userData = {};

// Fetch the location data for the current user.
load();

// Output the location of the user. Oops, it doesn't work! Why?
console.log('Hello! Your IP address is ' + userData.ip + ' and your country is ' + userData.country_name);

// The load function will detect the current visitor's ip and location with ajax, using the
// freegeoip service. It will place the returned data in the userData variable when it's ready.

function load(){

    $.getJSON('https://freegeoip.net/json/?callback=?', function(response){
        userData = response;

        // Uncomment this line to see what is returned:
        // console.log(response);
    });
}

即使 console.logload() 之後 函數調用,實際上是在獲取數據之前執行的。

10.濫用事件監聽器

假設您想監聽按鈕的點擊,但僅在選中復選框時。以下是初學者可能會做的事情(使用 jQuery):

var checkbox = $('input[type=checkbox]'),
    button = $('button');

// We want to listen for clicks only when the checkbox is marked.

checkbox.on('change', function(){

    // Is the checkbox checked?

    if(this.checked){

        // Listen for clicks on the button. 

        button.on('click', function(){

            // This alert is called more than once. Why?

            alert('Hello!');
        });
    }
});
<input type="checkbox" />

<button>Click me!</button>

<p>Click the checkbox a few times.</p>

這顯然是錯誤的。理想情況下,您應該只監聽一次事件,就像我們對複選框的更改事件所做的那樣。反複調用button.on('click' ..) 導致多個事件偵聽器永遠不會被刪除。我將把它作為練習留給讀者讓這個例子工作:)

結論

防止此類錯誤發生的最好方法是使用 JSHint。一些 IDE 提供與該工具的內置集成,因此在您編寫代碼時會檢查您的代碼。我希望你覺得這個列表很有趣。如果您有任何建議,請在評論部分提出!


Tutorial JavaScript 教程
  1. 通過示例為所有新手提供 Javascript

  2. 5 分鐘開發系列:Flexbox 佈局

  3. 我是具有 4 年經驗的金融科技領域的 NodeJS、AWS、無服務器和 NoSQL 的全棧開發人員,請問我任何問題!

  4. 如何從 JavaScript 中的函數中取回多個值

  5. 面向初學者的前端 Web 開發人員

  6. WebAudio Deep Note,第 2 部分:播放聲音

  7. 實驗:100kB 有限前端庫 RevolveR micro

  1. tsParticles 噴泉效果

  2. 以全屏模式查看代碼片段

  3. 設置間隔

  4. 你好🎃!!

  5. 使用 node 和 express 構建您自己的 API

  6. 如何通過 JavaScript 更改字體大小?

  7. 如何使用 React 和 MomentJS 創建一個 Countdown 組件

  1. Gatsby v4 為您的靜態網站帶來了什麼?

  2. Node.js 幕後花絮 #7 - 新的 V8

  3. 構建和發布你的 npm 包

  4. 使用 Stripe 和 Vue.js 創建訂閱系統