1.函式宣告的方式
JavaScript宣告函式有兩種選擇:函式宣告法,表示式定義法。
-
函式宣告法
function sum (num1 ,num2){ return num1+num2 } 複製程式碼
-
表示式定義法
var sum = function(num1,num2){ return num1+num2 }; 複製程式碼
2.扒一扒兩種函式宣告的區別
解析器會率先讀取函式宣告(也就是說函式宣告的優先順序較高),並使其在執行任何程式碼之前可以訪問(將函式宣告提升到程式碼樹頂部);至於函式表示式宣告,則必須等到解析器執行到它所在的程式碼行,才會執行,無法自動提升。
同樣的函式使用不同的定義方式,呼叫的時候會產生不同的效果。
// 函式宣告法
var num = add(1, 2);
console.log(num);// 3
function add(a, b) {
return a + b
}
// 函式表示式宣告
var num = add(1, 2);
console.log(num);//Uncaught TypeError: undefined is not a function
var add = function (a, b) {
return a + b
}
複製程式碼
我們來看一看這兩種宣告方式到底對程式碼產生了怎樣的影響。
首先看函式宣告,由於發生了程式碼提升,實際的程式碼如下
// 函式宣告法
function add(a, b) {
return a + b
}
var num = add(1, 2);
console.log(num);// 3
//function add(a, b) {
// return a + b
//}
複製程式碼
再看錶達式宣告法,同樣將變數add提升,add()函式呼叫的時候,只宣告瞭變數add,卻沒有進行賦值。(此時的add變數是undefined)實際的程式碼如下。
// 函式表示式宣告
var add;
var num = add(1, 2);
console.log(num);//Uncaught TypeError: undefined is not a function
add = function (a, b) {
return a + b
}
複製程式碼
3.關於變數提升和執行順序
JavaScript是解釋型語言,但它並不是逐行執行的。解析過程可以理解為兩個階段:一個是預處理階段,JavaScript將指令碼程式碼轉換為位元組碼,該過程中將所有定義的變數提升到程式碼樹頂端;第二個階段,JavaScript直譯器藉助執行環境,把位元組碼生成機械碼,該過程中才發生變數的賦值,並順序執行。
console.log(a);
//Error:a is not defined ,直接報錯,下面語句沒法執行,以下結果為註釋該句後結果
console.log(b) //undefined ,變數發生提升
var b="Test";
console.log(b);//Test
複製程式碼
也就說JavaScript值執行第一句語句之前就已經將函式/變數宣告預處理了
var b="Test" 相當於兩個語句
var b;(undefined結果的來源,在執行第一句語句之前已經解析)
b=”Test”(這句是順序執行的,在第二句之後執行)
這也是為什麼我們可以在方法宣告語句之前就呼叫方法的原因。
4.練一練
下面我們用一個經典的面試題目的一部分來對本篇文章進行總結
請問下面這段程式碼的執行結果是什麼?
function Foo() {
getName = function () {
alert (1);
};
return this;
}
Foo.getName = function () {
alert (2);
};
Foo.prototype.getName = function () {
alert (3);
};
var getName = function () {
alert (4);
};
function getName() {
alert (5);
}
getName()
複製程式碼
答案載入中...
答案載入中...
答案載入中...
答案載入中...
答案載入中...
答案載入中...
答案載入中...
答案載入中...
答案載入中...
答案載入中...
答案載入中...
答案載入中...
答案載入中...
答案載入中...
揭曉答案:
4
這裡我主要講解一下第二問中為什麼是4,其他的在後續文章中進行說明。上面的程式碼實際上是這個樣子滴
function Foo() {
getName = function () {
alert (1);
};
return this;
}
var getName;//只提升變數宣告
function getName() { //提升函式宣告,覆蓋var的宣告
alert (5);
}
Foo.getName = function () {
alert (2);
};
Foo.prototype.getName = function () {
alert (3);
};
getName = function () { //最終的賦值再次覆蓋function getName宣告
alert (4);
};
getName();//最終輸出4
複製程式碼
這下大家對函式宣告和函式表示式宣告,以及程式碼執行順序的基本知識就有所掌握了吧,歡迎批評指標~