JavaScript的一些坑~

146 阅读3分钟
  • 给一组数字排序
    大家都知道使用数组的sort()方法可以给字母数字(根据字符串的Unicode码)排序
var arr = [2,6,3,17,4,87,15];
arr.sort();//所以这样输出的是:[15, 17, 2, 3, 4, 6, 87]
要正确的排序一个数组你可以使用:
arr.sort(function (a,b){
    return a-b
})//输出:[2, 3, 4, 6, 15, 17, 87]
  • Replace 并不"代替"
var s = "bob";
var replaced = s.replace("b","l");
replaced === "lob";
s === "bob"

replace只会替换第一个匹配的字符串,如果你想替换匹配所有的字符串,那可以使用带有/g的正则表达式:

"bob".replace(/b/g,"l") === "lol";//true,替换所有匹配的字符串
  • 比较的时候要注意
"abc" === "abc"//true
1 === 1//true
···
"1" == 1 //true
"1" === 1//false
···
[1,2,4] === [1,2,4]//false
{a:1} === {a:1}//false
{} ==={}

问题1:双等比较时,如果2变的值一样,类型不一样,比较的时候会默认转换类型或者说忽略类型比较。而三等比较相对严格,不止要值一样,连值的类型也一样才可以。 问题2:大家都知道对象之间是不能比较的,而[1,2,4] 和 [1,2,4] 是两个独立的数组,他们只是包含的值一样,但是他们的引用是不不同的,所以无法比较(数组也是对象)

  • 数组不是原始数据类型
typeof {} === "object" //true
typeof "a" === "string" //true
typeof 1 === "number" //true
···
typeof [] === "array" // false
typeof [] === "object" //true

如果你想知道你的变量是不是数组,你可以使用Array,isArray(myArr);

  • 闭包
    这是一个很有名的面试题:
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… ? 你知道它为什么不是这样输出的吗? 你会怎样修改让它输出 0, 1, 2… ?
这里有两种可能的解决方法:

用 let 替代 var. Boom. 解决了.

let和var的不同在于作用域。var的作用域是最近的函数块,let的作用域是最近的封闭块,封闭块可以小于函数块(如果不在任何块中,则let和var都是全局的)。
替代方法: 用 bind:

Greeters.push(console.log.bind(null, i))

还有很多其他方法。这只是我的两个首选

  • 谈到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 不应该在实例上下文之外运行, 你可以在类的constructor中绑定它:

class Foo {
    constructor(name) {
        this.name = name
        this.greet = this.greet.bind(this)
    }
}

你还应该知道箭头函数( => )可以用来保留上下文。这个方法也可以:

asyncGreet() {
    this.someThingAsync()
        .then(() = > {
        this.greet()
    })
}

尽管我认为最后一种方法并不优雅。