Who said javascript was easy ?

Who said javascript was easy ?

谁说JavaScript容易?
扩展链接
扩展链接

Here’s a few tricks and traps that javascript beginners should probably know of. If you’re already an expert, feel free to read this with a knowing look.
这里有一些JavaScript初学者应该知道的技巧和陷阱。 如果你已经是一个专家,那就随意阅读.

1. Did you ever try to sort an array of numbers ?

1.你尝试过给一组数字排序吗?

Javascript sort()uses alphanumeric sort per default.
Javascript的sort()方法默认用来给数字排序

So[1,2,5,10].sort()will output[1, 10, 2, 5].
所以[1,2,5,10].sort()将会输出[1, 10, 2, 5].

To properly sort an array, you can use[1,2,5,10].sort((a, b) => a — b)
要正确的对数组进行排序的话,你可以使用[1,2,5,10].sort((a, b) => a — b)

Easy solution, provided you knew there was a problem in the first place :)
只要你一开始就知道这个坑的话,解决起来就很容易.

2. new Date() is just wonderful

2. new Date()很奇妙

new Date()can accept:
new Date()可以接受:

  • no argument: returns now

  • one argument x: returns 1st of january 1970, + x milliseconds. Unix people know why.

  • new Date(1, 1, 1) returns 1901, february , 1. Because you know, the first one means 1 year after 1900, the second one is the second month of the year (hence february) — who in his right mind would start indexing a table at indice 1  — , and the third one obviously is thefirstday of the month, so 1 — because sometimes the indices do start at 1 — .

  • Oh, and also new Date(2016, 1, 1) will not add 2016 years to 1900. It will simply represent the year 2016.

  • 没有参数就返回当前时间

  • 一个参数x就返回当前时间1970年1月1日,+ x毫秒,Unix的人知道为什么.

  • new Date(1,1,1)返回1901年,2月1日.因为你知道,第一个1意思是1900年后的1年,第二个1是这一年的第二个月(因此二月) - 二月的正确索引在索引表中为1 ,第三个1显然是这个月的第一天,所以是1 - 因为有时索引确实从1开始。

  • 哦,还有new Date(2016年,1,1)不会从2016年追加到1900年。它仅仅表示2016年。

3. Replace does not replace

3.Replace不替代

I find it to be a good thing, as I don’t like functions that mutate their input. You also should know that replace will only replace the first match:

我觉得这是件好事,因为我不喜欢函数去改变他输入的值,你应该也知道replace只会替换他第一个匹配:

let s = "bob"
const replaced = s.replace('b', 'l')
replaced === "lob" // first match only
s === "bob" // original string is remained unchanged

If you wish to replace all occurences, you can use a regex with/g:
如果你想替换所有,你可以使用带有/ g的正则表达式:

"bob".replace(/b/g, 'l') === 'lol' // replace all occurences

4.Careful with comparisons

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

Reason: [1,2,3] and [1,2,3] are two separate arrays. They just happen to contain the same values. They have distinct references and cannot be compared with===
理由:[1,2,3]和[1,2,3]是两个单独的数组.它们恰好包含相同的值,但是它们有不同的引用,不能用全等===比较

5. Array is no primitive type

5.数组不是原始数据类型

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

To know if your var is an array, you can still use Array.isArray(myVar)
想知道你的是不是数组, 你仍然可以使用Array.isArray(myVar)来判断

6. Closures

6.闭包

This one makes a well known javascript interview question:
这是一道有名的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

Did you expect it to output 0, 1, 2… ? Do you know why it does not ? How would you fix it ?
你是不是期望它输出0,1,2 ...? 你知道为什么它却没有输出吗? 你会如何修改它?

Let’s mention two of the possible solutions to this problem:
我们提出两个可能的解决方案:

Use let instead of var. Boom. solved.
使用let 来替换var. 立马解决.

“The difference [between let and var] is scoping. var is scoped to the nearest function block and let is scoped to the nearestenclosingblock (both are global if outside any block), which can be smaller than a function block.” (source)

"在let和var之间的差异是作用域,vari的作用域是最近的函数块,而let的作用域是最近的封闭块,封闭块可以小于函数块。(如果在任何块之外使用的话,let和var它们都是全局的) (source)

Alternative: usebind:
其他方法:使用 bind:
Greeters.push(console.log.bind(null, i))
There are plenty of other ways to do this. These are only my top-2 choices :)
其实有很多种方法去解决,这是我推荐的2种方法.

7. Speaking about bind

7.聊聊绑定

What do you think this will output ?
你认为这个将会输出什么?

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

One point for you if you think this will crash withCannot read property 'name' of undefined
Reason:greet is not run with proper context. Again, there are many ways to solve this.
理由:greet没有在正确的上下文运行,同样,是有很多方法可以解决.

I personally like
我个人比较喜欢


asyncGreet () {
  this.someThingAsync()
  .then(this.greet.bind(this))
}

This way you ensure that greet is called with your class instance as context.
这样做可以确保 greet可以被作为上下文的实例调用。

  • If you feel like greet should never be run out of context, you can also bind it in your class constructor:
  • 如果你不希望greet在实例上下文外运行,你还可以在类的constructor函数中绑定它.
class Foo {
  constructor (name) {
    this.name = name
    this.greet = this.greet.bind(this)
  }
}

You should also know that fat arrows (=>) can be used to preserve the context. This will also work:
你还应该知道箭头函数(=>)可以被用于保留上下文.它也可以这样使用:

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

翻译:bibi
原文链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容