1
var getLength = (function(){
.....
})();
2
function getLength (){
.....
}
天蓬老师2017-04-10 12:47:37
// 写法1
var getLength = function(){
.....
};
// 写法2
function getLength (){
.....
}
我觉得你想问的应该是这两种写法的区别是什么。
从执行的时候效果来看,两种写法都可以通过 getLength() 这种方式来调用去执行。
但是实际上这两种写法是不一样的。
我暂时给这种写法取个名字:变量声明及函数表达式的引用赋值。
写法1中包含了三层意思
getLength
getLength
赋值为匿名函数的引用就是说,写法1中的“函数声明”是在代码执行期——代码执行的时候——去“声明”的。
如果你想要执行 getLength()
,就必须在该行代码执行以后才能成功调用。
例如
getLength(); // 在赋值前执行
// TypeError: undefined is not a function
// 语法分析阶段不会报错,当代码执行到上面时,就会报 TypeError,因为 getLength 尚未赋值
var getLength = function(){
.....
};
写法2 可以是正宗的函数声明。
其作用就是声明一个名为 getLength 的函数。
函数声明是在语法分析阶段就已经完成(代码执行前)。故我们可以这样
getLength(); // 完全OK
function getLength(){
.....
};
不是语法糖,不是语法糖。
前文已经分析过,这两种书写方式对解释器来说是在不同阶段完成对函数的“声明”。
一个是在代码执行期完成“声明”,一个是在语法分析阶段完成声明。
// 例如下面的代码是用来获取函数的函数名,我们可以发现两种方式声明的函数是不一样的
var f = function() { console.log(arguments.callee.name) }
f();
// 此时返回 "" (空字符串)
function f() { console.log(arguments.callee.name) }
f();
// 此时返回 "f"
一般场景下,两种都能用。用法也差不多。只不过函数表达式赋值方式需要前置,而函数声明可以后置。
如果需要函数自己引用自己,这个时候推荐使用函数声明。因为 arguments.callee
在 ES5 strict mode 是禁用的。
例如
function F(n) {
if(n < 1) {
return 1
}
return F(n-1) + n;
}
如果是对象的方法声明,可以使用函数表达式赋值的方式。
例如
var obj = {
getValue : function() {return 'obj';}
}
又或者你要延迟声明函数,或者动态修改函数内容,可以使用函数表达式赋值方式。
其他场景,怎么舒服怎么用呗。
文中用引号包裹起来的声明其效果就是赋值。
var getLength = (function(){
.....
})();
关于作者原文中的这个函数。用一句话概括。
声明一个变量 getLength
,并将一个匿名函数的返回值赋值给他。
ringa_lee2017-04-10 12:47:37
最近在拜读《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;
//这个函数可能对环境有一些影响,但不会引入新的全局变量。
}());
PHP中文网2017-04-10 12:47:37
不同意见 @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
大家讲道理2017-04-10 12:47:37
@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()
然后通过正则表达式就能够提取出函数的名称了。
巴扎黑2017-04-10 12:47:37
简单来说 function fun() 这种方法声明的函数全局可用,在声明的前面也可以用 具有预载特性,第二种 fun=function() 要执行了之后才能被访问, 一般我推荐前者声明比较多,而后者看出js的概念和灵活性