Who said javascript was easy ?
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之间的差异是作用域,var
i的作用域是最近的函数块,而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
原文链接