转载请注明出处,保留原文链接以及作者信息

本文介绍了 JavaScript 初学者应该知道的一些技巧和陷阱。如果你是老司机,就当做回顾了,哪里有写的不好的地方欢迎指出。

1. 你是否尝试过对一个数字数组进行排序呢?

JavaScript 中的 sort() 默认是按字母排序的。所以比如你这样 [1,2,5,10].sort(),会输出 [1,10,2,5]

正确的排序可以使用 [1,2,5,10].sort((a, b) => a — b)

是不是很简单,这个知识点是告诉你第一种方式排序是有问题的。

2. new Date() 很好用

new Date() 可以接收:

  • 无参数:返回当前时间;
  • 1 个参数 x:返回 1970 年 1 月 1 日 + x 毫秒时间。Unix 的小伙伴知道为什么是这样;
  • new Date(1,1,1) 返回 1901 年 2 月 1 日:第一个 “1” 代表 1900 年以后的第 1 年;第二个 “1” 代表这一年的第 2 个月(并不是像你想象的那样从 1 月开始);第三个 “1” 代表这个月的第 1 天(这个确实是如你想象的那样从 1 开始)。
  • new Date(2017,1,1) :这并不是表示 1900 + 2017了,它就是表示 2017 年 1 月 1 日。

3. 替换,实际上并没有替换

对于原始串不被替换掉,我是双手赞同的,我不喜欢一个函数的输入总是在变化。另外你应该知道 replace 只会替换第一个匹配上的字符。

    let s = "bob"
const replaced = s.replace('b', 'l')
replaced === "lob" // 只替换第一个匹配上的
s === "bob" // 原始串始终没变

如果你想替换所有的,那就是用正则符 /g

    "bob".replace(/b/g, 'l') === 'lol' // 替换所有串

4. 小心使用比较

    // These are ok
'abc' === 'abc' // true
1 === 1 // true // These are not
[1,2,3] === [1,2,3] // false
{a: 1} === {a: 1} // false
{} === {} // false

原因:[1,2,3] 和 [1,2,3] 是两个数组,它们只是恰巧值相等罢了,他们的引用是不同的,所以不能用简单的 === 来比较。

5. 数组不是原始类型

    typeof {} === 'object'  // true
typeof 'a' === 'string' // true
typeof 1 === number // true
// But....
typeof [] === 'object' // true

想知道你的变量是不是数组,仍然可以使用 Array.isArray(myVar)

6. 闭包

这是很出名的一道 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

你预期的是输出:0,1,2...吗?你知道这是为什么吗?你知道怎么 fix 吗?

我来提两种可能的解决方案来解决这个问题:

  • 第一种:使用 let,不用 var。Duang!解决了~

let 和 var 的区别是作用域。var 的作用域是最近的函数块。而 let 的作用域是最近的封闭块。如果两个都是在块外的,那两个都是全局的。最近的封闭块,要比最近的函数块范围小。这里是源码

  • 第二种:使用 bind
    Greeters.push(console.log.bind(null, i))

还有很多方法可以解决这一问题,这里列出了我个人的两种最优选择。

7. 聊一聊 bind

你觉得下面的代码会输出什么?

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

给你点提示,你认为是否会抛出异常呢?Cannot read property 'name' of undefined

原因:greet 没有在恰当的上下文中执行。依旧,有很多种方法解决这个问题。

  • 第一种:我个人比较喜欢如下解决方法。
    asyncGreet () {
this.someThingAsync()
.then(this.greet.bind(this))
}

这种方式可以保证 greet 是在类已经实例化以后被调用。

  • 第二种:如果你想确保 greet 始终可以正确调用,可以绑定到构造函数中。
    class Foo {
constructor (name) {
this.name = name
this.greet = this.greet.bind(this)
}
}
  • 第三种:你还应该知道箭头函数(=>)可以保护上下文,也可以解决这个问题。
    asyncGreet () {
this.someThingAsync()
.then(() => {
this.greet()
})
}

虽然我觉得最后一种解决方案这个例子中很不优雅……

结束语

恭喜!到现在你知道了 JavaScript 中的一些坑,和一点技巧。JavaScript 中还有很多知识等待着你去学习,不过起码在这几个问题上,你不会再犯错误了。Cheers! \o/

如果你认为文章中还需要注意什么,或者添加什么,请让我知道


我最近正在写一本《React.js 小书》,对 React.js 感兴趣的童鞋,欢迎指点

谁说 JavaScript 很简单了?的更多相关文章

  1. 依然是关于我空间那篇申请的日志《JavaScript axError:Unexpected token ILLEGAL 很简单的代码……》

    接下来要讲的日志现在的标题已经更改为<很简单的代码,但是无法--> 这篇日志地址:http://www.cnblogs.com/herbertchina/p/4475092.html 经过 ...

  2. JavaScript实现简单的双向绑定

    很多的前端框架都支持数据双向绑定了,最近正好在看双向绑定的实现,就用Javascript写了几个简单的例子. 几个例子中尝试使用了下面的方式实现双向绑定: 发布/订阅模式 属性劫持 脏数据检测 发布/ ...

  3. 手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单

    手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单   手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发Chrome扩 ...

  4. js便签笔记(13)——jsonp其实很简单【ajax跨域请求】

    前两天被问到ajax跨域如何解决,还真被问住了,光知道有个什么jsonp,迷迷糊糊的没有说上来.抱着有问题必须解决的态度,我看了许多资料,原来如此... 为何一直知道jsonp,但一直迷迷糊糊的不明白 ...

  5. jquery实现很简单的DIV拖动

    今天用jquery实现了一个很简单的拖动...实现思路很简单  如下: 在thickbox 弹出层内实现拖拽DIV,那么得进行一下相对宽高的运算:必须加上相对于可见窗口宽高和弹出层宽高之间的差:    ...

  6. 一个很简单的jQuery插件实例教程(菜鸟级)

    很多公司的前端设计开发人员都是女孩子,而这些女孩子很多JavaScript技能都不是很好.而前端开发过程中,JavaScript技能又是必不可少的.所以,如果前端小MM正在为某个JavaScript效 ...

  7. 轻松搞定Ajax(分享下自己封装ajax函数,其实Ajax使用很简单,难是难在你得到数据后来怎样去使用这些数据)

    hey,guys!今天我们一起讨论下ajax吧!此文只适合有一定ajax基础,但还是模糊状态的同志,当然高手也可以略过~~~ 一.概念 Ajax(Asynchronous Javascript + X ...

  8. Javascript的简单测试环境

    在<JavaScript忍者秘籍>2.4测试条件基础知识中,作者给出了一个精简版的assert和assert组的实现,对于初学者而言,这无疑是一个很好的例子,既让我们得到了一个好用的小工具 ...

  9. jsonp其实很简单【ajax跨域请求】

    js便签笔记(13)——jsonp其实很简单[ajax跨域请求] 前两天被问到ajax跨域如何解决,还真被问住了,光知道有个什么jsonp,迷迷糊糊的没有说上来.抱着有问题必须解决的态度,我看了许多资 ...

随机推荐

  1. 3中转换JSON数据的方式

    一:前言 来公司一个星期,把最近做的东西梳理下,并把觉得有必要的知识点记载下,现在传数据很多都是用JSON来传数据,所以我就找了集中传json的方式,其实是有五种的,但是有一个我没有用过,太陌生了,上 ...

  2. 解决tomcat不支持中文路径的问题

    问题描述: 开发文件下载功能时,因为需求比较简单,要求下载一个说明文件.于是,直接给出了文件所在服务器的地址,通过链接直接下载此文件(因需求简单,未考虑安全方面的问题-_-||). 在这个过程中,文件 ...

  3. [BZOJ3275]Number解题报告|网络流

    Description 有N个正整数,需要从中选出一些数,使这些数的和最大.若两个数a,b同时满足以下条件,则a,b不能同时被选1:存在正整数C,使a*a+b*b=c*c2:gcd(a,b)=1 这道 ...

  4. 【STSRM12】夏令营(分治决策单调+主席树)

    [题意]n个数字分成k段,每一段的价值是段内不同数字的个数,求最大价值.n<=35000,k<=50. [算法]分治决策单调+主席树(可持久化线段树) [题解] f[i][j]表示前i天分 ...

  5. 【洛谷 P3306】[SDOI2013]随机数生成器 (BSGS)

    题目链接 怎么这么多随机数生成器 题意见原题. 很容易想到\(BSGS\)算法,但是递推式是\(X_{i+1}=(aX_i+b)\mod p\),这显然不是一个等比数列. 但是可以用矩阵乘法来求出第\ ...

  6. POJ1080(LCS变形)

    Human Gene Functions Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Oth ...

  7. guake 3.4发布,支持切分窗口

    guake是一款下拉式终端,美观实用. 近日发布了3.4版本,在3.4版本中支持了切分窗口功能.如图所示,还是比较实用的一个功能. 目前ubuntu仓库中还未更新,需要使用pip安装,或者自行从源码编 ...

  8. Google的C++开源代码项目

    Google的C++开源代码项目 http://www.open-open.com/lib/view/open1413873531356.html v8  -  V8 JavaScript Engin ...

  9. P2654 原核生物培养

    P2654 原核生物培养 题目描述 W教授最近正在研究一种原核生物,这种生物的生长方式很奇特,只能通过吃掉同类而生长.两个该种生物相遇,较大质量的会把较小的吃掉(相同的话就看RP了),吃掉后较大的生物 ...

  10. sudo cd为什么不能够执行

    问题描述 我想要cd到/etc/docker,但是它给我一个权限不够的错误,然后,我想到使用sudo cd /etc/docker时,它告诉我sudo: cd:找不到命令. 于是,郁闷的我就去上网找了 ...