JS中小括号的用法总结(自执行函数)
小括号用法
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();
// 这里的报错原因感觉是这样的 1: function (){console.log(123)}(); // 报错 Uncaught SyntaxError: Function statements require a function name 2:function asdfas(){console.log(123)}();// 报错 Uncaught SyntaxError: Unexpected token ')'
1浏览器解析执行为: function (){console.log(123)();// 一个匿名函数表达式紧跟(),浏览器会解析该圆括号为函数调用(定义一个函数有三种方式:函数声明,new,赋值函数表达式),该匿名函数表达式既不是赋值函数表达式,也不是函数声明,也没有使用new操作符声明,由于定义函数的默认方式是函数声明,所以这里解析该匿名表达式为函数声明,所以报函数声明语法错误 new function (a){console.log(a)}(1)// => 1 可以证明这一点 2浏览器解析执行为: function asdfas(){console.log(123)} // 根据代码从上到下从左往右的解析机制,这是一个完整的函数声明语句,没有问题继续往后解析 (); // 是圆括号内表达式不能为空,所以报了圆括号的语法错误
综上所诉: 1、一个匿名函数表达式,其后紧跟跟圆括号计算符,圆括号被当做了函数调用语句,此时这个匿名函数表达式会被浏览器解析为函数声明,导致报函数声明错误 2、一个函数声明(具名函数表达式)后面紧跟一个圆括号,会被解析成两条语句: 一个函数声明语句和圆括号运算符语句,由于圆括号的优先级较普通函数表达式高,且圆括号运算符必须有一个表达式,所以报了圆括号运算符的语法错误
function a(){console.log(123)}(1); // => 1 a() // => 123 可以证明上诉案例2