js有三種創(chuàng)建函數(shù)的方式:
1.function語句(也叫函數(shù)聲明)
function sum(a, b) {
return a + b;
}
sum(1, 2); // 3
2. 函數(shù)直接量讯沈,又叫函數(shù)字面量
它是一個表達式而不是語句。
var sum = function(a, b) {
return a + b;
}
sum(1, 2); // 3
上述代碼就是函數(shù)通過直接量的方式進行定義祝迂。函數(shù)直接量是一個表達式睦尽,它可以定義匿名函數(shù)。函數(shù)直接量的語法和function語句十分相似型雳,只不過当凡, 它被用作表達式的一部分,而不是用作語句了纠俭。在函數(shù)直接量定義中沿量,右側(cè)的function所定義的是匿名函數(shù),并將這個匿名函數(shù)的引用傳遞給表達式左側(cè)冤荆。接下來執(zhí)行了sum(1, 2),就運行了這個函數(shù)朴则。
ps: 雖然函數(shù)字面量是一個匿名函數(shù),但語法允許為其指定任意一個函數(shù)名钓简,當寫遞歸函數(shù)時可以調(diào)用它自己乌妒,使用Function()構(gòu)造函數(shù)則不行。
var test = function factorial(x) {
if (x <= 1) {
return 1;
} else {
return x * factorial(x-1);
}
};
test(3); // 6
// 這個也是閉包的一種用法
3. 構(gòu)造函數(shù)
它也是一個函數(shù)表達式外邓。
var sum = new Function('a', 'b', 'return a + b;');
sum(1, 2); // 3
比較區(qū)別
首先我們來看看1撤蚊、2之間的區(qū)別:
大家都知道有這樣一個原理:函數(shù)聲明格式
的函數(shù)存在函數(shù)聲明提前,而函數(shù)表達式
损话、構(gòu)造函數(shù)
都不存在函數(shù)聲明提前侦啸。
所以咱們的js解析器就會先讀取函數(shù)聲明格式
的函數(shù)槽唾,讓其在執(zhí)行任何代碼之前就可以訪問;而函數(shù)表達式
則必須要等到j(luò)s解析器執(zhí)行到它所在的位置的時候才會被真正執(zhí)行光涂。
自執(zhí)行函數(shù)
嚴格來說也叫函數(shù)表達式
庞萍,它主要用于創(chuàng)建一個新的作用域,在此作用域內(nèi)聲明的變量顶捷,不會和其他作用域內(nèi)的變量沖突或混淆挂绰,大多以匿名函數(shù)方式存在屎篱,并且立即自動執(zhí)行服赎。
(function(a, b) {
console.log(a + b); // 3
})(1, 2)
var sum=(function(a, b){
return a + b;
})(1, 2);
console.log(sum); // 3
接下來我們來看第三種方式:
- 采用new Function的方式,這樣會導(dǎo)致解析器會解析兩次代碼(第一次是解析常規(guī)ECMAScript代碼交播,第二次則是解析傳入構(gòu)造函數(shù)中的字符串)重虑,從而影響性能。一般我們很少用到秦士。
- 我們來看一個閉包的三種函數(shù)實現(xiàn)的栗子:
var a = 1;
function test1(){
var a = 2; // 局部變量
function test(){ return a; }; // function語句式缺厉,a=2
return test();
}
test1(); // 2
var a = 1;
function test1(){
var a = 2; // 局部變量
var test = function(){ return a;}; // 函數(shù)直接量,a=2 隧土,兩者都是函數(shù)的作用域
return test();
}
test1(); // 2
var a = 1;
function test2(){
var a = 2; // 局部變量
var test = new Function("return a;"); // 構(gòu)造函數(shù)提针,頂級的作用域,相當于在全局new一個函數(shù)曹傀,只能找到全局的a=1
return test();
}
test2(); // 1 沒想到是1吧
用Function()構(gòu)造函數(shù)創(chuàng)建一個函數(shù)時并不遵循典型的作用域辐脖,它一直把它當作是頂級函數(shù)來執(zhí)行。頂級的作用域皆愉,相當于在全局new一個函數(shù)嗜价,只能找到全局的變量。
總結(jié)
最后用一張表格總結(jié)一下:
--- | function語句 | 函數(shù)直接量 | 構(gòu)造函數(shù) |
---|---|---|---|
創(chuàng)建形式 | function f(){} | var f = function(){} | var f = new Function() |
是否有名 | 有名字 | 匿名 | 匿名 |
性質(zhì) | 靜態(tài) | 靜態(tài) | 動態(tài) |
解析機制 | 優(yōu)先解析 | 順序解析 | 順序解析幕庐,且解析兩次 |
性能 | 效率高 | 效率高 | 效率低 |
作用域 | 函數(shù)作用域 | 函數(shù)作用域 | 全局函數(shù)(具有頂級作用域)久锥,僅訪問全局變量 |
動態(tài)和靜態(tài)的區(qū)別
:function語句式 和 函數(shù)直接量 被javascript解釋一次,放在了內(nèi)存异剥,以后用到的話直接調(diào)用瑟由,占用內(nèi)存,所以說是“靜態(tài)”的冤寿。而構(gòu)造函數(shù)式是每一次調(diào)用都動態(tài)新建一個歹苦,用完之后就銷毀了,不占用內(nèi)存疚沐,所以說是“動態(tài)”的暂氯。所以,有些程序只希望調(diào)用一次亮蛔,就可以用動態(tài)的構(gòu)造函數(shù)式痴施。
總結(jié): js的三種創(chuàng)建方式都說完了,感覺講還是比較清楚吧,參考學(xué)習(xí)了各方面的資料辣吃,這里加上自己的理解做了一次匯總动遭。希望對自己也是一種提升。
轉(zhuǎn)載自:
https://www.jscwwd.com/article/5e70976667f5cf03e3a5990b
更多前端文章在益碼憑川博客網(wǎng)站