1.聲明函數和函數表達式瀏覽器
function foo(){} // 聲明,由於它是程序的一部分函數
var bar = function foo(){}; // 表達式,由於它是賦值表達式的一部分spa
new function bar(){}; // 表達式,由於它是new表達式對象
(function(){作用域
function bar(){} // 聲明,由於它是函數體的一部分字符串
})();io
--------------------------------------------------function
function foo(){} // 函數聲明變量
(function foo(){}); // 函數表達式:包含在分組操做符內程序
try {
(var x = 5); // 分組操做符,只能包含表達式而不能包含語句:這裏的var就是語句
} catch(err) {// SyntaxError
}
-----------------
try {
{
"x": 5
}; // "{" 和 "}" 作解析成代碼塊
} catch (err) {
// SyntaxError
}
({
"x": 5
}); // 分組操做符強制將"{" 和 "}"做爲對象字面量來解析、
表達式和聲明存在着十分微妙的差異,首先,函數聲明會在任何表達式被解析和求值以前先被解析和求值,即便你的聲明在代碼的最後一行,它也會在同做用域內第一個表達式以前被解析/求值,參考以下例子,函數fn是在alert以後聲明的,可是在alert執行的時候,fn已經有定義了:
alert(fn());
function fn() {
return 'Hello world!';
}
另外,還有一點須要提醒一下,函數聲明在條件語句內雖然能夠用,可是沒有被標準化,也就是說不一樣的環境可能有不一樣的執行結果,因此這樣狀況下,最好使用函數表達式:
// 由於有的瀏覽器會返回first的這個function,而有的瀏覽器返回的倒是第二個
if (true) {
function foo() {
return 'first';
}
} else {
function foo() {
return 'second';
}
}
foo();
// 相反,這樣狀況,咱們要用函數表達式
var foo;
if (true) {
foo = function() {
return 'first';
};
} else {
foo = function() {
return 'second';
};
}
foo();
2.函數語句
函數語句不是在變量初始化期間聲明的,而是在運行時聲明的——與函數表達式同樣。不過,函數語句的標識符一旦聲明能在函數的整個做用域生效了。標識符有效性正是致使函數語句與函數表達式不一樣的關鍵所在
// 此刻,foo還沒用聲明
typeof foo; // "undefined"
if (true) {
// 進入這裏之後,foo就被聲明在整個做用域內了
function foo() {
return 1;
}
} else {
// 歷來不會走到這裏,因此這裏的foo也不會被聲明
function foo() {
return 2;
}
}
typeof foo; // "function"
------------------
符合標準的代碼來模式上面例子中的函數語句
var foo;
if (true) {
foo = function foo() {
return 1;
};
} else {
foo = function foo() {
return 2;
};
}
----------------------------
.函數語句和函數聲明(或命名函數表達式)的字符串表示相似,也包括標識符:
if (true) {
function foo() {
return 1;
}
}
String(foo); // function foo() { return 1; }
函數語句覆蓋函數聲明的方式不正確。在這些早期的實現中,函數語句不知何故不能覆蓋函數聲明:
function foo() {
return 1;
}
if (true) {
// 用函數語句重寫
function foo() {
return 2;
}
}
foo(); // FF3如下返回1,FF3.5以上返回2
// 不過,若是前面是函數表達式,則沒用問題
var foo = function() {
return 1;
};
if (true) {
function foo() {
return 2;
}
}
foo(); // 全部版本都返回2
3.命名函數表達式