1
var getLength = (function(){
.....
})();
2
function getLength (){
.....
}
最近在拜读《JavaScript语言精粹》。书中113页相关内容如下:
JavaScript既有function语句,同时也有function表达式。这令人困惑,因为它们看起来好像就是相同的。一个function语句就是其值为一个函数的var语句的速记形式。
下面的语句:
function foo() {}
意思相当于:
var foo = function foo() {};
在整本书中,我一直使用的是第2种形式,因为它能明确表示foo是一个包含一个函数值的变量。要用好这门语言,理解函数就是数值是很重要的。
function语句在解析时会发生被提升的情况。这意味着不管function被放置在哪里,它会被移动到被定义时所在作用域的顶层。这放宽了函数必须先声明后使用的要求,而我认为这会导致混乱。在if语句中使用function语句也是被禁止的。结果表明大多数的浏览器都允许在if语句里使用function语句,但它们在解析时的处理各不相同。这就造成了可移植性的问题。
一个语句不能以一个函数表达式开头,因为官方的语法假定以单词function开头的语句是一个function语句。解决方法时把函数调用括在一个圆括号之中。
(function () {
var hidden_variable;
//这个函数可能对环境有一些影响,但不会引入新的全局变量。
}());
不同意见 @HJin.me
var getlength = (function(){console.log("run")})()
申明一个getlength变量,但是并没有给它赋值
(function(){})() 是一个立即执行的函数
getlength 能得到的是这个匿名函数的返回值
不认同你所说的变量 getLength 赋值为匿名函数的引用
如果是引用那么getlength() 就应该是个可执行的函数
但是考虑下
var getlength = (function(){
console.log("this is a test");
})()
对getlength typeof 发现会是一个undefined
@HJin.me 回答的非常棒!但是有一点补充一下,就是即使在 ES5 strict mode 下,要调用自己也是可以用匿名函数的方式的:
var a = 0,
b = 111,
c = function b() {
if (a == 2) {return}
a++
b()
}
c()
最终 a == 2 && b == 111
如果在函数 b 外部调用 b()
,会报错说:"TypeError: number is not a function"
这样的写法也可以用于 shim JavaScript 在低级浏览器下没有 .name
属性的困境,通过将函数 .toString()
然后通过正则表达式就能够提取出函数的名称了。
简单来说 function fun() 这种方法声明的函数全局可用,在声明的前面也可以用 具有预载特性,第二种 fun=function() 要执行了之后才能被访问, 一般我推荐前者声明比较多,而后者看出js的概念和灵活性
8 回答4.7k 阅读✓ 已解决
6 回答3.4k 阅读✓ 已解决
5 回答2.8k 阅读✓ 已解决
5 回答6.3k 阅读✓ 已解决
4 回答2.2k 阅读✓ 已解决
4 回答2.8k 阅读✓ 已解决
3 回答2.4k 阅读✓ 已解决
我觉得你想问的应该是这两种写法的区别是什么。
从执行的时候效果来看,两种写法都可以通过 getLength() 这种方式来调用去执行。
但是实际上这两种写法是不一样的。
写法1
我暂时给这种写法取个名字:变量声明及函数表达式的引用赋值。
写法1中包含了三层意思
getLength
getLength
赋值为匿名函数的引用就是说,写法1中的“函数声明”是在代码执行期——代码执行的时候——去“声明”的。
如果你想要执行
getLength()
,就必须在该行代码执行以后才能成功调用。例如
写法2
写法2 可以是正宗的函数声明。
其作用就是声明一个名为 getLength 的函数。
函数声明是在语法分析阶段就已经完成(代码执行前)。故我们可以这样
语法糖?
不是语法糖,不是语法糖。
前文已经分析过,这两种书写方式对解释器来说是在不同阶段完成对函数的“声明”。
一个是在代码执行期完成“声明”,一个是在语法分析阶段完成声明。
应用场景
一般场景下,两种都能用。用法也差不多。只不过函数表达式赋值方式需要前置,而函数声明可以后置。
如果需要函数自己引用自己,这个时候推荐使用函数声明。因为
arguments.callee
在 ES5 strict mode 是禁用的。例如
如果是对象的方法声明,可以使用函数表达式赋值的方式。
例如
又或者你要延迟声明函数,或者动态修改函数内容,可以使用函数表达式赋值方式。
其他场景,怎么舒服怎么用呗。
PS
文中用引号包裹起来的声明其效果就是赋值。
关于作者原文中的这个函数。用一句话概括。
声明一个变量
getLength
,并将一个匿名函数的返回值赋值给他。