译者按: 漫漫编程路,总有一些坑让你泪流满面。

原文: Who said javascript was easy ?

译者: Fundebug

为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习

这里我们针对JavaScript初学者给出一些技巧和列出一些陷阱。如果你已经是一个砖家,也可以读一读。

1. 你是否尝试过对数组元素进行排序?

JavaScript默认使用字典序(alphanumeric)来排序。因此,[1,2,5,10].sort()的结果是[1, 10, 2, 5]

如果你想正确的排序,应该这样做:[1,2,5,10].sort((a, b) => a - b)

2. new Date() 十分好用

new Date()可以接收:

  1. - 不接收任何参数:返回当前时间;
  2. - 接收一个参数`x`: 返回197011 + `x`毫秒的值。
  3. - `new Date(1, 1, 1)`返回190121号。
  4. - 然而....,`new Date(2016, 1, 1)`不会在1900年的基础上加2016,而只是表示2016年。

3. 替换函数没有真的替换?

let s = "bob"
const replaced = s.replace('b', 'l')
replaced === "lob" // 只会替换掉第一个b
s === "bob" // 并且s的值不会变
  1. 如果你想把所有的b都替换掉,要使用正则:
"bob".replace(/b/g, 'l') === 'lol'

4. 谨慎对待比较运算

// 这些可以
'abc' === 'abc' // true
1 === 1 // true
 
// 然而这些不行
[1,2,3] === [1,2,3] // false
{a: 1} === {a: 1} // false
{} === {} // false
  1. 因为[1,2,3]和[1,2,3]是两个不同的数组,只是它们的元素碰巧相同。因此,不能简单的通过`===`来判断。

5. 数组不是基础类型

typeof {} === 'object' // true
typeof 'a' === 'string' // true
typeof 1 === number // true
// 但是....
typeof [] === 'object' // true
  1. 如果要判断一个变量`var`是否是数组,你需要使用`Array.isArray(var)`

6. 闭包

  1. 这是一个经典的JavaScript面试题:
const Greeters = []
for (var i = 0 ; i < 10 ; i++) {
Greeters.push(function () { return console.log(i) })
}
 
Greeters[0]() // 10
Greeters[1]() // 10
Greeters[2]() // 10
  1. 虽然期望输出0,1,2,...,然而实际上却不会。知道如何Debug嘛? 有两种方法: - 使用`let`而不是`var`。备注:可以参考Fundebug的另一篇博客[ES6"let"能替代"var"吗?](https://blog.fundebug.com/2017/05/04/why-you-should-not-use-var/) - 使用`bind`函数。备注:可以参考Fundebug的另一篇博客[JavaScript初学者必看“this”](https://blog.fundebug.com/2017/05/17/javascript-this-for-beginners/)
Greeters.push(console.log.bind(null, i))
  1. 当然,还有很多解法。这两种是我最喜欢的!

7. 关于bind

  1. 下面这段代码会输出什么结果?
class Foo {
constructor (name) {
this.name = name
}
 
greet () {
console.log('hello, this is ', this.name)
}
 
someThingAsync () {
return Promise.resolve()
}
 
asyncGreet () {
this.someThingAsync()
.then(this.greet)
}
}
 
new Foo('dog').asyncGreet()
  1. 如果你说程序会崩溃,并且报错:Cannot read property 'name' of undefined 因为第16行的`geet`没有在正确的环境下执行。当然,也有很多方法解决这个BUG - 我喜欢使用`bind`函数来解决问题:
asyncGreet () {
this.someThingAsync()
.then(this.greet.bind(this))
}
  1. 这样会确保`greet`会被Foo的实例调用,而不是局部的函数的`this` - 如果你想要`greet`永远不会绑定到错误的作用域,你可以在构造函数里面使用`bind`来绑定。
class Foo {
constructor (name) {
this.name = name
this.greet = this.greet.bind(this)
}
}
  1. - 你也可以使用箭头函数(=>)来防止作用域被修改。备注:可以参考Fundebug的另一篇博客[JavaScript初学者必看“箭头函数”](https://blog.fundebug.com/2017/05/25/arrow-function-for-beginner/)。
asyncGreet () {
this.someThingAsync()
.then(() => {
this.greet()
})
}

8. Math.min()比Math.max()大

Math.min() < Math.max() // false
  1. 因为Math.min() 返回 Infinity, Math.max()返回 -Infinity

欢迎加入我们Fundebug全栈BUG监控交流群: 622902485

  1. 版权声明:
  2. 转载时请注明作者Fundebug以及本文地址:
  3. https://blog.fundebug.com/2017/06/28/who-said-js-was-easy/

JavaScript中8个常见的陷阱的更多相关文章

  1. JavaScript 中 4 种常见的内存泄露陷阱

    了解 JavaScript 的内存泄露和解决方式! 在这篇文章中我们将要探索客户端 JavaScript 代码中常见的一些内存泄漏的情况,并且学习如何使用 Chrome 的开发工具来发现他们.读一读吧 ...

  2. JavaScript中五种常见运算符

    一. in运算符 in运算符希望它的左操作数是一个字符串或可以转换为字符串,希望它的右操作数是一个对象.如果右侧的对象拥有一个名为左操作数值的属性名,那么表达式返回true.例如: var point ...

  3. javascript中function 函数递归的陷阱问题

    //看下这个递归方法,最后输出的值function fn(i){ i++; if(i<10){ fn(i); } else{ return i; } } var result = fn(0); ...

  4. JavaScript中几种常见的兼容问题及解决方案

    在js中好用的东西一般都存在兼容问题,以下,我整理了一些常用的兼容处理方法,自己用的时候可以把他们放在一个JS文件中,需要用到时候直接引入,会比较方便. 一.获取非行内样式 function getS ...

  5. javascript中五种常见的DOM方法

    getElementById将返回一个与那个有着给定id属性值的元素节点对应的对象. <html xmlns="http://www.w3.org/1999/xhtml"&g ...

  6. Javascript中的循环变量声明,到底应该放在哪儿?

    相信很多Javascript开发者都在声明循环变量时犹豫过var i到底应该放在哪里:放在不同的位置会对程序的运行产生怎样的影响?哪一种方式符合Javascript的语言规范?哪一种方式和ecma标准 ...

  7. JavaScript中函数式编程中文翻译

    JavaScript 中的函数式编程 原著由 Dan Mantyla 编写 近几年来,随着 Haskell.Scala.Clojure 等学院派原生支持函数式编程的偏门语言越来越受到关注,同时主流的 ...

  8. JavaScript 中常见的内存泄露陷阱(摘)

    内存泄露是每个开发者最终都不得不面对的问题.即便使用自动内存管理的语言,你还是会碰到一些内存泄漏的情况.内存泄露会导致一系列问题,比如:运行缓慢,崩溃,高延迟,甚至一些与其他应用相关的问题. 什么是内 ...

  9. JavaScript中的this陷阱的最全收集

    JavaScript来自一门健全的语言,所以你可能觉得JavaScript中的this和其他面向对象的语言如java的this一样,是指存储在实例属性中的值.事实并非如此,在JavaScript中,最 ...

随机推荐

  1. Open-Source Cybersecurity Infrastructure

    https://www.linkedin.com/pulse/open-source-cybersecurity-infrastructure-adrian/ The increased maturi ...

  2. 【MySQL】sql_mode引起的一个问题和总结

    [背景] 之前项目中,项目组计划将现场的MySQL5.5升级到5.7,以提升主从同步性能.使用半同步复制,以及解决一些现场问题等.安排测试组进行验证,测试同事反馈实验室环境中发现有入库失败,我查看了e ...

  3. 使用webmagic爬虫对百度百科进行简单的爬取

    分析要爬取的网页源码: 1.打开要分析的网页,查看源代码,找到要爬取的内容: (选择网页里的一部分右击审查元素也行) 2.导入jar包,这个就直接去网上下吧: 3.写爬虫: package com.g ...

  4. 【Hadoop】2、Hadoop高可用集群部署

    1.服务器设置 集群规划 Namenode-Hadoop管理节点 10.25.24.92 10.25.24.93 Datanode-Hadoop数据存储节点 10.25.24.89 10.25.24. ...

  5. eos开发(一) eos开发环境搭建

    区块链最近挺火的,我又是个非常缺钱的人,所以紧跟了潮流一头扎进区块链的研究中. 这EOS项目是目前比较火的一个项目,相信很多朋友拿到这份EOS的源代码后都会一脸懵逼,因为……这代码写得太高级了,老纸看 ...

  6. Azure认知服务之Face API上手体验

    Azure认知服务:Face API Face API是Azure认知服务之一,Face API有两个主要功能: 人脸检测 Face API可在图像中以高精度人脸位置检测多达64个人脸.图像可以通过文 ...

  7. springboot Aop 统一处理Web请求日志

    1.增加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  8. 静态和实例方法区别-java

    静态方法和实例方法的区别主要体现在两个方面:   在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式.而实例方法只有后面这 ...

  9. [NewLife.XCode]数据层缓存(网站性能翻10倍)

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...

  10. shell 脚本实现文件对称加密

    前言 之前手机里管理密码的脚本,都是直接编写进纯文本然后进行多次归档及压缩来实现不明文存储,一直觉得不太安全,于是昨天晚上编写脚本实现了简单的文件对称加密. 网上文章都利用 openssl 来进行文件 ...