zoukankan      html  css  js  c++  java
  • 谁说 JavaScript 很简单了?

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

    本文介绍了 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 感兴趣的童鞋,欢迎指点

  • 相关阅读:
    28完全背包+扩展欧几里得(包子凑数)
    HDU 3527 SPY
    POJ 3615 Cow Hurdles
    POJ 3620 Avoid The Lakes
    POJ 3036 Honeycomb Walk
    HDU 2352 Verdis Quo
    HDU 2368 Alfredo's Pizza Restaurant
    HDU 2700 Parity
    HDU 3763 CDs
    POJ 3279 Fliptile
  • 原文地址:https://www.cnblogs.com/libin-1/p/6696671.html
Copyright © 2011-2022 走看看