JavaScript中的小技巧
- Time: 02 November 2014
- Categories:
- frontend 7
- Tags:
- javascript 8
每种编程语言里都有一些小伎俩,有些确实能带来方便,有些则只是纯蛋疼。这里收集一些常见的JavaScript伎俩,按需自取。
!function foo(){}()
对于!function foo(){}()
,有以下几点:
- 运算符
()
比!
的优先级高,所以它等价于!(function foo(){}());
!(statement);
会触发JavaScript引擎去解析statement,然后取其结果的布尔反值- 该语句的目的就是执行这个函数,它等价于
(function foo(){})();
直接使用function foo(){}()
会导致语法错误,因为
function foo() {}
是一个函数声明语句,末尾没有;
号,对它的解析到}
号为止,你不能在后面接(
。想要调用foo
,只能使用foo();
。
因此,这个伎俩的目的只是为了省一个字符:!function foo(){}()
VS (function foo(){})();
!!variant
JavaScript中没有!!
运算符,它实际上是两次!
逻辑运算,结果是把任意一个JavaScript对象转化为一个布尔值。这其中,如果variant本身一个falsy value,那么!!variant
是布尔假。否则为真。
console.log(!!1); // true
Boolean(1) === !!1; // true
console.log(!!""); // false
Boolean("") === !!""; //true
可以把它看作是布尔值转换运算。但如果你是为了在if
语句中使用,大可不必这样做。因为JavaScript引擎会对if(statemen){}
中的statement
自动执行这个布尔值转换操作。比如,以下代码会把bar
当作布尔真值来执行。
var bar = {a: 1};
if(bar){
console.log(true);
}else{
console.log(fasle);
}
函数参数的缺省值
在C++/PHP/Python中定义方法的时候都能为参数指定一个默认值,但JavaScript语言没有这个机制。因此我们只能仿造。一般是这样来做的:
function myFunc(requiredArg, optionalArg){
optionalArg = (typeof optionalArg === "undefined") ? "defaultValue" : optionalArg;
//do stuff
}
如果你确定这个参数是一个非falsy value的对象,还可以简化(这是我用得最多的方式):
function myFunc(requiredArg, optionalArg){
optionalArg = optionalArg || defaultValue;
//do stuff
}
注意:
- 跟Python一样,你只能把带默认值的参数放在参数列表的最后。
- ECMAScript6中的Function已经加入该特性,Firefox中已经支持:Default parameters
+
运算符
这个问题中有很多蛋疼的例子,在这里说它的目的是提醒大家:严谨地使用+
运算符。以下是使用+
的蛋疼示例,运行示例请参考jsfidde
- [] + []
- // an empty string
- [] + {}
- [object Object]
- {} + []
- 0
- {} + {}
- NaN
- Array(16).join(“wat” + 1)
- wat1wat1wat1wat1wat1wat1wat1wat1wat1wat1wat1wat1wat1wat1wat1
- Array(16).join(“wat” - 1)
- NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
实际上以上结果都是遵循ECMAScript5的执行结果。对于+
运算符的规定为 The Addition operator ( + ):
- 不限制运算数必须为primitive
- 首先将两个操作数转化为primitive - ToPrimitive
- 将一个object转化为primitive就是返回其
default value
,如果该object有toString()
方法,将返回该方法的值 - 对于Array来说,就是调用其
.join()
方法 - 对于object来说,调用
toString()
将返回"[object Object]"
以上规范能解释大部分使用+
的场合,但还有两个示例需要进一步的解释:
- {} + []
{}
会被解析为一个block,而不是一个对象(除非你使用({})
使它成为一个表达式)- 因此
{} + []
等价于+[]
+operand
将返回toNumber(ToPrimitive(operand))
+[]
将返回toNumber("")
,也就是0
- {} + {}
- 由上可知它将返回
toNumber("[object Object]")
- 根据toNumber()的定义,这无法转成number,因此返回NaN
- 由上可知它将返回
太复杂。实际使用中,最好保证+
的两个操作数均为primitive类型,不能是object类型。