摘要:中函數(shù)是一等公民。小明小明調用函數(shù)時,傳遞給函數(shù)的值被稱為函數(shù)的實參值傳遞,對應位置的函數(shù)參數(shù)名叫作形參。所以不推薦使用構造函數(shù)創(chuàng)建函數(shù)因為它需要的函數(shù)體作為字符串可能會阻止一些引擎優(yōu)化也會引起瀏覽器資源回收等問題。
函數(shù)
之前幾節(jié)中圍繞著函數(shù)梳理了 this、原型鏈、作用域鏈、閉包等內容,這一節(jié)梳理一下函數(shù)本身的一些特點。
javascript 中函數(shù)是一等公民。 并且函數(shù)也是對象,因為它們可以像任何其他對象一樣具有屬性和方法。它們與其他對象的區(qū)別在于函數(shù)可以被調用。簡而言之,它們是 Function 對象。
一個函數(shù)是可以通過外部代碼調用的一個“子程序”,函數(shù)內部包含了執(zhí)行語句或表達式。每個自定義函數(shù)都是Function的實例,并繼承Function的所有屬性和方法,而Function 是語言本身提供的編程接口。
function foo (name) { console.log(`hello, ${name}`) } var res = foo(`小明`) // "hello, 小明" console.log(res)
調用函數(shù)時,傳遞給函數(shù)的值被稱為函數(shù)的實參(值傳遞),對應位置的函數(shù)參數(shù)名叫作形參。如果實參是一個包含原始值(數(shù)字,字符串,布爾值)的變量,則就算函數(shù)在內部改變了對應形參的值,返回后,該實參變量的值也不會改變。如果實參是一個對象引用,則對應形參會和該實參指向同一個對象。假如函數(shù)在內部改變了對應形參的值,返回后,實參指向的對象的值也會改.(歡迎查看參數(shù)傳值一節(jié))
如果函數(shù)內部沒有通過return返回一個值,則函數(shù)會默認返回undefined.
函數(shù)在實際開發(fā)中承擔著代碼分塊、 功能封裝等任務。
函數(shù)定義// 函數(shù)申明 foo() let a = 1 function foo () { console.log(a) } // 函數(shù)表達式 (函數(shù)變量) let too = function (){ console.log("hello") } too() // Function 構造函數(shù)實例化一個函數(shù) let bar = new Function("console.log("hello")") bar() // 箭頭函數(shù) let fns = () => { console.log("hello") } fns()
需要注意的是函數(shù)申明和函數(shù)表達式在變量提升時的區(qū)別,強烈建議閱讀變量對象相關內容:詳情。同時函數(shù)申明的函數(shù)名稱不能被改變,而函數(shù)表達式賦值給的變量可以被重新賦值。
函數(shù)的各種定義方式就不深入,這里需要注意的是通過使用構造函數(shù)(new Function())方式創(chuàng)建的函數(shù),在每次調用的時候都會解析一次。所以不推薦使用 Function 構造函數(shù)創(chuàng)建函數(shù), 因為它需要的函數(shù)體作為字符串可能會阻止一些 JS 引擎優(yōu)化,也會引起瀏覽器資源回收等問題。
argumentsarguments同this一樣是函數(shù)提供給函數(shù)內部使用的一個屬性(ES6中箭頭函數(shù)沒有)。通過arguments我們可以獲取調用函數(shù)時傳遞進來的實參, 該屬性是一個類數(shù)組對象,我們可以像數(shù)組一樣進行數(shù)值的讀取。
function foo () { let a = arguments[0] // 獲取函數(shù)的第一個參數(shù) let b = arguments[1] // 獲取函數(shù)的第二個餐宿 // 遍歷函數(shù)的所有參數(shù) for (let arg in arguments) { console.log(`${arg}: ${arguments[arg]}`) } arguments[2] = 1122 } foo(1, 2, 3)
雖然arguments是類似于數(shù)組,但是除了通過索引獲取元素和length屬性外,不能使用push、pop等方法。如果確實要進行修改操作,可以將其轉換為真正的數(shù)組:
let args = Array.prototype.slice.call(arguments) let args = [].slice.call(arguments) // ES2015 let args = Array.from(arguments)自執(zhí)行函數(shù)
把函數(shù)定義和函數(shù)執(zhí)行結合到一起就是立即執(zhí)行函數(shù),也叫自執(zhí)行函數(shù)。
在官方術語中叫做 IIFE( 立即調用函數(shù)表達式),是在定義時就會立即執(zhí)行的函數(shù)。被稱為自執(zhí)行匿名函數(shù)的設計模式,主要包括兩部分:
第一部分是包圍在 圓括號運算符() 里的一個匿名函數(shù),這個匿名函數(shù)擁有獨立的詞法作用域。這不僅避免了外界訪問此 IIFE 中的變量,而且又不會污染全局作用域。借用這個特性我們可以對局部功能進行封裝,只暴露很少的方法給外部環(huán)境,這也是很多第三方庫的封裝方法之一。
第二部分再一次使用 () 創(chuàng)建了一個立即執(zhí)行函數(shù)表達式,JavaScript 引擎到此將直接執(zhí)行函數(shù)。
當函數(shù)變成立即執(zhí)行的函數(shù)表達式時,表達式中的變量不能從外部訪問:
(function () { var a = 1 })() console.log(a) // a is not defined
將 IIFE 分配給一個變量,不是存儲 IIFE 本身,而是存儲 IIFE 執(zhí)行后返回的結果:
let bar = (function (){ let a = 123 return a })() console.log(bar) // 123
別外自執(zhí)行函數(shù)還有一些其他使用方式:
// 下面2個括弧()都會立即執(zhí)行 (function(){ /* code */ }()); (function(){ /* code */ })(); // 由于括弧()和JS的&&,異或,逗號等操作符是在函數(shù)表達式和函數(shù)聲明上消除歧義的 // 所以一旦解析器知道其中一個已經(jīng)是表達式了,其它的也都默認為表達式了 var i = function(){ /* code */ }(); true && function(){ /* code */ }(); 0, function(){ /* code */ }(); // 如果你不在意返回值,或者不怕難以閱讀 // 你甚至可以在function前面加一元操作符號 !function(){ /* code */ }(); ~function(){ /* code */ }(); -function(){ /* code */ }(); +function(){ /* code */ }(); // 上面這種使用一元表達式這種方式其實是不太常見的 // 而且有時候肯定在一些場景下存在一些弊端,因為一元表達式會有一個不為undefined的返回值 // 要想返回值為undefined,那么最保險的就是使用void關鍵字 void function(){/* code */}();
()左邊必須是一個函數(shù)表達式,而不是一個函數(shù)申明。自執(zhí)行函數(shù)也會用在模塊封裝的場景下。
閉包函數(shù)和函數(shù)聲明時的詞法作用域形成閉包。我們可以使用閉包來保存變量、封裝不需要暴露的私有屬性和方法。
var scope = "global scope"; function checkscope(){ var scope = "local scope"; function f(){ return scope; } return f; } var foo = checkscope(); foo(); // "local scope"
徹底理解閉包的最好途徑就是理解閉包的由來,閉包的產(chǎn)生和作用域鏈有密切關系。在作用域鏈一節(jié)已經(jīng)梳理過閉包的原理。
函數(shù)式編程未完成
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/107968.html
摘要:構造函數(shù)和實例都通過屬性指向了原形。代碼示例是構造函數(shù)的實例的屬性與的屬性保存的值相等,即他們指向同一個對象原形。 講清楚之javascript原型 標簽: javascript javascript 中原形是一個比較難于理解的概念。javascript 權威指南在原形這一章也花了大量的篇幅進行介紹,也許你已經(jīng)讀過javascript 權威指南,或者已經(jīng)是讀第N篇了,然而這篇文章的目...
摘要:棧底為全局上下文,棧頂為當前正在執(zhí)行的上下文。位于棧頂?shù)纳舷挛膱?zhí)行完畢后會自動出棧,依次向下直至所有上下文運行完畢,最后瀏覽器關閉時全局上下文被銷毀。 講清楚之執(zhí)行上下文 標簽 : javascript 什么是執(zhí)行上下文? 當 JavaScript 代碼執(zhí)行一段可執(zhí)行代碼時,會創(chuàng)建對應的上下文(execution context)并將該上下文壓入上下文棧(context stack...
摘要:講清楚之參數(shù)傳值參數(shù)傳值是指函數(shù)調用時,給函數(shù)傳遞配置或運行參數(shù)的行為,包括通過進行傳值。所以對的賦值會改變上下文棧中標識符保存的具體值此時如果使用的是按引用傳遞,則變量所指向的對象因該也被賦值為。 講清楚之 javascript 參數(shù)傳值 參數(shù)傳值是指函數(shù)調用時,給函數(shù)傳遞配置或運行參數(shù)的行為,包括通過call、apply 進行傳值。 在實際開發(fā)中,我們總結javascript參數(shù)傳...
閱讀 1914·2021-09-24 09:48
閱讀 3256·2021-08-26 14:14
閱讀 1711·2021-08-20 09:36
閱讀 1505·2019-08-30 15:55
閱讀 3658·2019-08-26 17:15
閱讀 1461·2019-08-26 12:09
閱讀 635·2019-08-26 11:59
閱讀 3359·2019-08-26 11:57