使用函式陳述式在宣告變數時,在創造階段就會把整個函式給載入進來。
這樣做的優點是:可以在程式碼宣告該函式之前使用它。
callName();
function callName() {
console.log('呼叫小明'); // 呼叫小明
}
拆解 : 函式陳述式在創造階段,記憶體空間已包含函式完整內容了。
//創造階段
function callName() {
console.log('呼叫小明');
}
//執行
callName();
callName( ); 可以在表達式之後呼叫
var callName = function(){
console.log('呼叫小明');
}
callName(); // 呼叫小明
若 callName( ); 在表達式之前呼叫,會跳錯
console.log(callName); // undefined
callName(); // callName is not a function
var callName = function(){
console.log('呼叫小明');
}
拆解
// 創造階段
var callName; // 先準備一個記憶體空間,但沒有值,屬於 undefined
// 執行
callName = function(){ // 執行時,才把 function() 賦予到此變數上
console.log('呼叫小明'); // callName 尚在未賦值階段,所以會跳錯
}
callName();
// 陳述式 與 表達式
function callName() {
console.log('呼叫小明 1');
}
var callName = function () {
console.log('呼叫小明 2');
}
callName(); // 呼叫小明 2
拆解
// 創造階段
function callName() {
console.log('呼叫小明 1');
}
var callName;
// 執行,賦予值
callName = function () {
console.log('呼叫小明 2');
} // 此時變數 callName 被函式覆蓋過去
callName(); // 呼叫小明 2
試著把 (8行) callName( ); 往前移
// 創造階段
function callName() {
console.log('呼叫小明 1');
}
var callName;
// 執行,賦予值
callName(); // 呼叫小明 1 (因為變數重複宣告是沒有用的)
callName = function () {
console.log('呼叫小明 2');
}
變數與函式的拉升的不同之處在於,變數的拉升只有宣告部份,而函式的拉升是整個函式,因此函式在宣告前是可以執行的。
callName(); // undefined
function callName() {
console.log(Ming);
}
var Ming = '小明';
拆解
// 創造階段
function callName() {
console.log(Ming);
}
var Ming;
// 執行,賦予值
callName(); // 目前此函式所取的值是全域變數的Ming,此時Ming尚未被賦予值,所以為undefined
Ming = '小明';
function callName() {
console.log('小明');
}
callName();
function callName() {
console.log('杰倫');
}
callName();
拆解 : 兩個函式名稱都相同,後面會覆蓋前面的 ; 執行時只會取到 "杰倫"
// 創造階段
function callName() {
console.log('小明');
}
function callName() {
console.log('杰倫');
}
// 執行,賦予值
callName(); // 杰倫
callName(); // 杰倫
範例如下,同名函式 foo 和變數 foo,由於函式優先,因此 foo() 得到 1 而非 undefined() 的結果 TypeError。
foo(); // 1
var foo;
function foo() {
console.log(1);
}
foo = 2;
拆解
// 創造階段
function foo() {
console.log(1);
}
// 執行,賦予值
foo(); // 1
foo = 2;
whosName();
function whosName() {
if (name) {
name = '杰倫';
}
}
var name = '小明';
console.log(name); // 小明
拆解
// 創造階段
function whosName() { // whosName() 因函式優先被提升到最上方
if (name) {
name = '杰倫';
}
}
var name; // 宣告一個全域變數name,此時尚未被賦於值(顯示undifined)
// 執行,賦予值
whosName();
// whosName();在進入if判斷式之前,並沒有宣告變數name,因此向外尋找。
// 此時全域變數name還未被賦予值,if判斷結果為false,函式執行中斷並跳出。
name = '小明'; // name 被重新賦予值 小明
console.log(name); // 答案為小明