你可能不知道的javascript特性,入坑之旅
比较
- 相等
console.log('' == '0') // false
console.log(0 == '') // true
console.log('' === '0') // false
console.log(0 === '') // false
在 Javascript 中需要注意一点是 == 与 === 的区别。在使用 == 比较两个变量时,会发生隐式类型转换,例如,自动将字符串类型转换为数字类型。避免隐式类型转换带来的问题,可以使用 === 进行比较。
这里 != 和 !== 也存在同样的问题,因此,除了空检查,推荐使用 === 和 !== ,
- 严格相等
如果比较两个对象是否相等,仅仅使用 == 或 === 是不够的
console.log({ a: 123 } == { a: 123 }) // false
console.log({ a: 123 } === { a: 123 }) // false
这里可以借助 javascript 库,deep-equal,npm install deep-equal -S
import * as deepEqual from 'deep-equal'
console.log(deepEqual({ a: 123 }, { a: 123 })) // true
引用
除了字面量外,javascript 中的任何对象都是值引用,这意味着这些对象一旦发生变化,源赋值都会变化
var foo = {}
var bar = foo
foo.baz = 123
console.log(bar.baz) // 123
任何对象引用赋值,不希望只是值引用(数据改变不影响源数据),可以使用深拷贝
null 和 undefined
- 变量没有初始化:undefined
- 变量不可用:null
console.log(undefined == undefined) // true
console.log(null == undefined) // true
console.log(0 == undefined) // false
console.log('' == undefined) // false
console.log(false == undefined) // false
推荐使用 == null 来检查 undefined 和 null,因为通常不希望区分它们
你可以执行 == undefined ,但 == null 更常用
建议使用 == null 来检查是否相等,但是不要把它们用于根级别的检查。严格模式下,如果使用 foo,并且 foo 为 undefined ,那么你将会得到一个 referenceError 的异常,且整个调用堆栈都会展开。
JSON 和序列化
JSON 标准支持编码 null,但不支持 undefined 。当 JSON 编码具有 null 属性的对象时,这个属性将会包含 null 值;然而当一个属性 undefined 时,在编码后,它会被删除。
JSON.stringify({a: null, b: undefined}) // {a: null}
this
在函数内对 this 关键字的访问实际上都是由函数的实际调用方式控制的。它通常被称为调用上下文
function eat() {
console.log(this)
}
eat() // 输出全局的信息,如浏览器中的 window
let animal = {
eat
}
animal.eat() // 输出 animal,因为 eat 是在 animal 中调用的
闭包
在 javascript 中,闭包是指一个函数有权力访问定义在它外部作用域的任何变量。
function animal(name) {
var outName = name
function eat() {
console.log(outName)
}
eat()
}
animal('dog')
即使在返回外部函数之后,内部函数依然可以从外部作用域中访问变量。这是因为变量始终绑定在内部函数中,并没有依赖于外部函数。
function createCounter() {
let count = 0
return {
increment() {
count++
},
getCount() {
return count
}
}
}
const counter = createCounter()
counter.increment()
console.log(counter.getCount())
counter.increment()
console.log(counter.getCount())
数字
- 十进制
在 javascript 中,只有一个数字类型。它是一个双精度的64位的 number。下面
console.log(0.1 + 0.2) // 0.30000000000004
对出真正的十进制数据,可以用 big.js 处理。以及在金融计算上使用数学时
big.js 这类的第三方库,是专为下面两个目的设计的。
- 完美的十进制运算
- 超出整数值的安全计算
- NaN
当一个被计算出来的数字不能表示为一个有效数字时, javascript 会返回一个特殊的 NaN 值,一个典型的例子就是虚数。
console.log(Math.sqrt(-1)) // NaN
相等的检查不适用于 NaN 值,要使用 Number.isNaN 来代替,
// bad
console.log(NaN === NaN) // false
// good
console.log(Number.isNaN(NaN)) // true
truthy
javascript 中一个 truthy 的概念,用来定义在某些位置上被评估为 true 的代码,如 if 条件语句中的 boolean、&&、|| 操作符
变量类型 | 什么时候是 falsy 的 | 什么时候是 truthy 的 |
boolean | false | true |
string | ” | 其它任何字符串 |
number | 0、NaN | 其它任何数字 |
null | 总是 | 从不 |
undefined | 总是 | 从不 |
任何其它对象,包括 {} 和 [] | 从不 | 总是 |
通过操作符 !! ,可以很容易地将某些值转化为布尔类型的值(true 或 false),在很多地方都可以使用操作符 !!
// 直接使用变量
const hasName = !!name
// 作为类的成员
const obj = {
hasName: !!name
}
// React.js
{!!name && <div>{name}</div>}