Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS中小括号的用法总结(自执行函数) #19

Open
Kelichao opened this issue Nov 3, 2016 · 1 comment
Open

JS中小括号的用法总结(自执行函数) #19

Kelichao opened this issue Nov 3, 2016 · 1 comment

Comments

@Kelichao
Copy link
Owner

Kelichao commented Nov 3, 2016

小括号用法

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();
@Kelichao Kelichao changed the title JS中小括号的用法总结 JS中小括号的用法总结(自执行函数) Nov 4, 2016
@Fujitomy
Copy link

Fujitomy commented Apr 8, 2021

// 这里的报错原因感觉是这样的
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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants