小括号用法
1. 改变运算符的优先级
var a = 4 * (1 + 2); console.log(a);// 12
2.函数声明和函数调用参数列表:
function func(a,b){ //代码 } func(1,2);
// 参数列表注意点 function a(b=222,c=333) { console.log(b);// 111 console.log(arguments[0]);// 111 } a(111);
3.在循环语句中调用
if(a>1){ //代码 } while(i<len){ //代码 } for(var i=0;i<len;i++){ //代码 }
4.函数声明,函数表达式,立即调用函数
函数声明必须带有标识符,也就是函数名,但是函数表达式方式,标识符带不带都可以。
// 函数声明(会提前) function func(){ // ... } // 函数表达式(不会提前) var func=function(){ // ... }
要区分一个代码是函数声明还是函数表达式,那要看代码的应用上下文。
- 如果有运算符号,那它就是函数表达式。
- 如果没有运算符号而且不在条件判断语句中,就说明是函数声明,无法直接加()进行调用(运算符包括赋值号跟括号)
- 如果在条件语句中,函数声明也会强行被当做函数表达式执行。
所以如果函数被当做函数表达式来进行调用时,this指向始终为window 间接引用
var a = { b:function() { console.log(this) } };
var x = (c=a.b); x();// window
三种自执行函数
(function(){ //代码1 })();
(function(){ //代码2 }());
!function(){ //代码3 }();
上面三个语句都是在运算符相关上下文中,所以都是表达式,就可以强制调用了,下面做一下分析:
1.(function(){})(),(function(){})是一个表达式,会强制其理解成函数直接量方式,也就是表达式方式创建函数,(function(){})它会返回函数对象的引用,最后使用小括号()调用此函数。
2.(function(){}()),如果不用外面包裹的小括号,{}就会理解为复合语句,那么function(){}就被理解为函数声明,但是没有标识符,所以会报错,使用小括号以后,就会变成表达式,也会被理解为直接量方式。
3.!function(){}(),原理同上,!也是一个运算符,所以在原理同上。还可以有其他运算符。
_所以只要通过运算符将语句改成了该表达式,不管这是个什么样的表达式< (,),-,+,_ >,都会先返回函数体的引用,然后再执行其他操作,如进行调用()*
var x = ""; //只要有运算符号,就不会报错 x + function() {console.log(this)}(); x - function() {console.log(this)}(); x * function() {console.log(this)}();
var x = 1; x + function() {return 2;}(); console.log(x);// 1
// 函数体不能直接调用,调用的是函数所在的地址 function (){console.log(123)}();// 报错 function asdfas(){console.log(123)}();// 报错
// 但是如果存在运算符号<(,),-,+,*>则是先忽略执行函数的 () var x = function (){console.log(123)}(); var y = function asdfas(){console.log(123)}();
// 效果类似于先将函数体的地址拿到类似于 var x = function (){console.log(123)};// 拿到了函数体的地址 var y = function asdfas(){console.log(123)};// 拿到了函数体的地址
// 通过地址进行调用 x(); y();
ps: