一般定义函数
const foo = function(){console.log('666')}; foo(); //666
或者
function foo(){console.log('666')}; foo(); //666
那么下面这个这么解释?
const foo = function foo(){console.log('666')}; foo();
温故而知新,可以为师矣。 博客:www.ouyangke.com
其实题主觉得第三种写法奇怪,且看起来鸡肋,是因为没有搞懂这种写法的正确用法,第二个例子比较直观
简单来说,第一个和第三个都是函数表达式,第二个是函数声明。第三个是比较特殊一些的函数表达式,拥有特殊能力。
要来解释这个问题,我们需要搞懂'What, How, Why'.
所以第一个和第二个区别主要在于他们声明的时机不一致,函数表达式是在代码执行到那条语句的时候才会给变量赋值,而函数声明会在进入当前函数执行上下文的时候就提前赋值。
直观的例子
console.log(foo); // undefined var foo = function(){}; console.log(foo); // function(){} console.log(bar); // function(){} function bar() {} console.log(bar); // function(){}
对于第三种,直观的例子是这样
console.log(foo); // undefined var foo = function bar(){ console.log(bar); // function(){...} console.log(foo); // undefined }; console.log(foo); // function(){} console.log(bar); // undefined
所以看出区别了吧,就是这种写法的函数标示符和函数声明的不一样,它可以在函数内部访问到,但是函数外部是访问不到的。所以我们看到很多地方会这么写,有一个好处就是在使用递归的时候调用自身的时候,函数是有名字的,比较直观
为什么会这样?
浏览器解析的时候其实是把表达式后面的标示符付给了当前的函数对象,所以上面的例子中
foo.name; // bar
而在函数内的执行上下文中,当前函数对象是在作用域中的,所以可以在内部调用
以上
补充一下第三种定义的解释: 它本身是一个函数表达式,并不是函数定义语句. 函数表达式是可以有函数名的,但是这个函数名只能在该函数表达式内部使用.参考 Javascript权威指南 8.1 函数定义这一小节:
函数表达式
函数定义语句
MDN JavaScript 函数中定义函数有多种方法:
函数声明 (函数语句)
函数表达式 (function expression)
函数生成器声明 (function* 语句)
函数生成器表达式 (function* 表达式)
箭头函数表达式 (=>)
Function构造函数
生成器函数的构造函数
对于楼主的问题这里只谈函数声明和函数表达式。
1) 函数声明
function name([param[, param[, ... param]]]) { statements }
2) 函数表达式
let function_expression = function [name]([param1[, param2[, ..., paramN]]]) { statements };
name是可选的,当省略函数名name的时候,函数就成为了匿名函数。
看到这里自然不必再继续谈为啥有第三种写法了,不然确实钻牛角尖了,但是这里不得不说一下函数声明和函数表达式的区别,主要体现在变量提升的问题上:
JavaScript 仅提升声明,而不是初始化。函数声明下存在变量提升,而函数表达式下不会,所以函数表达式先调用函数,再声明函数会报错。
第一个foo => 没名字的function第三个foo => 有名字的function
foo
function
但是两个function的执行内容是一样的的,都把这个函数赋值给foo变量初始化对象
至于第二个,就是正常的声明一个函数,然后调用函数
第三种就是赋值操作呀!把函数赋值给foo!如果在之前使用foo就是为定义和平时提前使用一个未定义的变量一样啊!如果你在你所写的那段代码后console.log(foo)是打印整个函数,加个()自然就是调用此函数了!记住单等号在js中永远是赋值操作等号右边就是赋值的内容就好了!不要想的太麻烦了!就算等号后面再写100个函数最多也只是进行了一个赋值而已!
其实题主觉得第三种写法奇怪,且看起来鸡肋,是因为没有搞懂这种写法的正确用法,第二个例子比较直观
简单来说,第一个和第三个都是函数表达式,第二个是函数声明。第三个是比较特殊一些的函数表达式,拥有特殊能力。
要来解释这个问题,我们需要搞懂'What, How, Why'.
所以第一个和第二个区别主要在于他们声明的时机不一致,函数表达式是在代码执行到那条语句的时候才会给变量赋值,而函数声明会在进入当前函数执行上下文的时候就提前赋值。
直观的例子
对于第三种,直观的例子是这样
所以看出区别了吧,就是这种写法的函数标示符和函数声明的不一样,它可以在函数内部访问到,但是函数外部是访问不到的。所以我们看到很多地方会这么写,有一个好处就是在使用递归的时候调用自身的时候,函数是有名字的,比较直观
为什么会这样?
浏览器解析的时候其实是把表达式后面的标示符付给了当前的函数对象,所以上面的例子中
而在函数内的执行上下文中,当前函数对象是在作用域中的,所以可以在内部调用
以上
补充一下第三种定义的解释: 它本身是一个
函数表达式
,并不是函数定义语句
. 函数表达式是可以有函数名的,但是这个函数名只能在该函数表达式内部使用.参考 Javascript权威指南 8.1 函数定义这一小节:
MDN JavaScript 函数中定义函数有多种方法:
函数声明 (函数语句)
函数表达式 (function expression)
函数生成器声明 (function* 语句)
函数生成器表达式 (function* 表达式)
箭头函数表达式 (=>)
Function构造函数
生成器函数的构造函数
对于楼主的问题这里只谈函数声明和函数表达式。
1) 函数声明
2) 函数表达式
name是可选的,当省略函数名name的时候,函数就成为了匿名函数。
看到这里自然不必再继续谈为啥有第三种写法了,不然确实钻牛角尖了,但是这里不得不说一下函数声明和函数表达式的区别,主要体现在变量提升的问题上:
JavaScript 仅提升声明,而不是初始化。函数声明下存在变量提升,而函数表达式下不会,所以函数表达式先调用函数,再声明函数会报错。
第一个
foo
=> 没名字的function
第三个
foo
=> 有名字的function
但是两个
function
的执行内容是一样的的,都把这个函数赋值给foo
变量初始化对象至于第二个,就是正常的声明一个函数,然后调用函数
第三种就是赋值操作呀!把函数赋值给foo!如果在之前使用foo就是为定义和平时提前使用一个未定义的变量一样啊!如果你在你所写的那段代码后console.log(foo)是打印整个函数,加个()自然就是调用此函数了!
记住单等号在js中永远是赋值操作等号右边就是赋值的内容就好了!不要想的太麻烦了!就算等号后面再写100个函数最多也只是进行了一个赋值而已!