10 个 JavaScript 容易犯的错误

发布于 2018-07-04 12:26:58 字数 7045 浏览 1720 评论 0

JavaScript 是一门简单的解释性编程语言,学习他很容易,但是语言语法去不严谨,这就导致了很容易犯错,但是却不知道错误在哪里,今天给大家列举一下 10 个 JavaScript 容易犯的错误,也许你也这么干过?

1、失踪的大括号

JavaScript 经常犯的错误是省略括号后面的声明,比如:ifelsewhilefor 。虽然这是允许的,你必须格外小心,因为这种做法往往是隐藏的问题和错误的来源。看下面的例子:

// 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() 函数是缩进的,看起来好像是属于 if 语句。所以大括号总是围绕其中的代码块是一个很好的做法,即使是只有一个语句。

2、缺少分号

当 JavaScript 解析,有一个过程称为自动分号的插入。顾名思义,解析器是乐意把你丢失分号。此功能的目的是使 JavaScript 更平易近人,更容易写的初学者。然而你应该总是包含分号,因为有在忽略他们的危险。这里有一个例子:

console.log('Welcome the fellowship!')

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

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

因为有一个分号在 3 行失踪,解析器假设开始第五行是一个尝试使用数组语法访问属性访问器,而不是一个独立的数组,这不是我们所期望的,在一个类型错误的结果。解决方法是简单的–总是写分号。 一些有经验的 JavaScript 开发者喜欢把分号但是,他们非常清楚的错误,这可能会导致和知道如何阻止他们。

3、变量类型强制转换

JavaScript 是动态类型。这意味着,你不需要指定类型时,宣布一个新的变量,并可以自由转让或将其价值。这使得写的不是像 C 或 Java 非常容易,但是你打开门,潜在的错误,在其他语言被编译步骤期间。这里有一个例子:

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

});

这个问题可以通过使用固定的容易 parseInt(textBox.value, 10) 将字符串转换为数字前加 10。 取决于你如何使用变量,运行时可能会决定它应该在一种或另一种类型转换。这是众所周知的类型强制。为了防止类型的隐式转换比较时,变量如果报表,您可以使用严格的平等的检查(===)。

4、忘了 var

另一种做法,初学者是有罪的,被遗忘的使用 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 线,它会自动插入一个分号,然后解释 C 和 D 5 号线的声明为全局。这将导致外部 C 变量的值的变化。

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);阅读更多JavaScript的陷阱在这里。

为了解决这个问题,你不应该使用小数,如果你需要绝对正确使用整数。

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

解决的方法很简单:尝试总是使用文字符号。

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、使用 eval

它被认为是一种不好的做法,当你使用它的时候,有一个更好、更快的方法。

/* 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('http://freegeoip.net/json/?callback=?', function(response){
        userData = response;
        // Uncomment this line to see what is returned:
        // console.log(response);
    });
}

即使 console.log 之后 load() 函数调用,它实际上是在执行读取数据。

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

这显然是错误的。理想情况下,你应该倾听事件只有一次,就像我们是复选框的变化事件。在按钮上绑定多个 button.on('click') 事件侦听器,是永远不会被删除,结果我将把它作为为读者做这工作的一个练习。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84960 人气
更多

推荐作者

烙印

文章 0 评论 0

singlesman

文章 0 评论 0

独孤求败

文章 0 评论 0

晨钟暮鼓

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文