函數是JavaScript非常重要的一部分,它被稱爲第一等公民,可以看出它的地位是何等尊貴何等重要。根據我一貫的作風,會深入原理性的東西,那這篇文章主要來挖掘函數聲明與函數表達式相關知識。
在JavaScript中定義一個函數有四種方式
- 函數聲明
- 函數表達式
- ES6裏箭頭函數
- new Function()
函數聲明
語法
function 函數名(參數){
要執行的代碼
}
調用
- 函數名(參數)
- 函數名.call(函數名,參數)
- 函數名.apply(函數名,[參數])
- new 函數名(參數)
- 定時器
- 把函數聲明變成函數表達式再調用
- ES6裏的模版字符串
function fn(text){
console.log(text);
}
fn('直接調用');
fn.call(fn,'用call調用');
fn.apply(fn,['用apply調用']);
new fn('用new調用');
setTimeout(fn('用定時器調用'));
(function fn(text){
console.log(text);
})('轉成函數表達式後調用');
fn`用模版字符串調用`; //ES6里語法
函數表達式
語法
var/let/const 變量=function(參數){
要執行的代碼
}
調用
- 函數名(參數)
- 函數名.call(函數名,參數)
- 函數名.apply(函數名,[參數])
- new 函數名(參數)
- 直接在後面加上一對小括號
- 定時器
- ES6裏的模版字符串
- 以被賦值的形式出現(根據具體形式調用)
const fn=function(text){
console.log(text);
};
fn('直接調用');
fn.call(fn,'用call調用');
fn.apply(fn,['用apply調用']);
new fn('用new調用');
const fn2=function(text){
console.log(text);
}('直接在後面加小括號調用');
setTimeout(fn('用定時器調用'));
fn`用模版字符串調用`;
document.onclick=function(){
console.log('以被賦值的形式出現也是一個函數表達式');
};
函數聲明與函數表達式的區別
- 函數聲明必須帶有標識符(函數名稱),函數表達式則可以省略
- 表達式裏的名字不能在函數外面用,只能在函數內部用
- 函數有一個name屬性,指向緊跟在function關鍵字之後的那個函數名。如果函數表達式沒有名字,那name屬性指向變量名
- 函數聲明會被預解析,函數表達式不會
//1、名字
//函數聲明必需帶名字
function fn(){};
//function(){}; //報錯,沒有名字
//函數表達式可以沒有名字
let fn1=function(){};
(function(){});
!function(){};
//表達式名字的作用
let fn2=function newFn(){
console.log(newFn); //可以在這裏面用。有一個作用就是在這裏用遞歸
};
fn2();
//newFn(); //報錯,不能在外面用
//name屬性
console.log(
fn.name, //fn
fn1.name, //fn1 表達式沒有名字,name屬性指向表達式變量名
fn2.name //newFn
);
//2、預解析
fn3();
function fn3(){
console.log('fn3');
}
//fn4(); //報錯,不會被預解析
let fn4=function(){
console.log('fn4');
}
自執行函數
自執行函數也叫立即調用的函數表達式(IIFE)。它的作用爲我們不用主動地去調用函數,它會自己調用,對於做模塊化、處理組件是非常有用的。
首先來看一個問題,調用函數最簡單的方法就是加一對小括號,那我在函數聲明的末尾加一對括號後,這個函數能否調用呢?
function fn(){
console.log(1);
}(); //報錯
const fn1=function(){
console.log('表達式執行');
}(); //執行函數
函數聲明不能直接調用的原因
- 小括號裏只能放表達式,不能放語句
- function關鍵字即可以當作語句,也可以當作表達式。但js規定function關鍵字出現在行首,一律解釋成語句
解決方法:不要讓function出現在行首
- 用括號把function主體括起來,轉成表達式。後面加括號運行
- 藉助運算符(new + - ! ~ typeof , && ||...)
因爲運算符會把表達式執行,執行後得出結果了才能運算
//小括號裏只能放表達式
(
if(true){
console.log(1);
}
)//報錯,括號裏不能放語句
(1);
(1+2);
([1]);
({});
function fn(){
console.log('函數聲明執行');
}(1); //符合語法,但是函數不會執行
//想要執行就必需把函數聲明轉成表達式,而小括號裏只能放表達式,利用這個特徵把函數放在一對括號裏,再加一對括號就能執行
(function fn(){
console.log('函數聲明執行');
})();
//或者這樣也可以執行
(function fn(){
console.log('函數聲明執行');
}());
只要把函數聲明轉成表達式,再加上括號就可以聲明。那就有很多稀奇古怪的方式來執行函數
0+function(text){
console.log(text);
}('與數字相加變成表達式');
true&&function(text){
console.log(text);
}('利用邏輯運算符變成表達式');
false||function(text){
console.log(text);
}('利用邏輯運算符變成表達式');
0,function(text){
console.log(text);
}('利用逗號運算符變成表達式');
//二進制位取反運算符
~function(text){
console.log(text);
}('前面加上+-!~變成表達式');
new function(text){
console.log(text);
}('利用new運算符變成表達式');
typeof function(text){
console.log(text);
}('利用typeof運算符變成表達式');