JavaScript函數(shù)增強(qiáng)以及額外知識(shí)
一、函數(shù)增強(qiáng)
1.1 函數(shù)對(duì)象的屬性
JavaScript中函數(shù)也是一個(gè)對(duì)象,那么對(duì)象中就可以有屬性和方法。
name:一個(gè)函數(shù)的名字我們可以通過(guò)name來(lái)訪問(wèn)
length:屬性length用于返回函數(shù)參數(shù)的個(gè)數(shù)
- 注意:rest參數(shù)是不參與參數(shù)的個(gè)數(shù)的
var bar = function(m, n, ...others) { } console.log(bar.length) // 2
1.2 arguments
arguments 是一個(gè)對(duì)應(yīng)于傳遞給函數(shù)的參數(shù)的類(lèi)數(shù)組(array-like)對(duì)象
注意:array-like意味著它不是一個(gè)數(shù)組類(lèi)型,而是一個(gè)對(duì)象類(lèi)型:
擁有數(shù)組的一些特性,比如說(shuō)length,比如可以通過(guò)index索引來(lái)訪問(wèn)
沒(méi)有數(shù)組的一些方法,比如filter、map等
arguments轉(zhuǎn)數(shù)組
遍歷arguments,添加到一個(gè)新數(shù)組中
調(diào)用數(shù)組slice函數(shù)的apply方法
ES6中的兩個(gè)方法[].slice.apply(arguments) Array.prototype.slice.apply(arguments)
- Array.from
- […arguments]
- 特別注意:箭頭函數(shù)不綁定arguments
- 在箭頭函數(shù)中使用arguments會(huì)去上層作用域查找
function foo() { var bar = () => { console.log(arguments) } bar() } foo(111, 222) // Arguments(2) [111, 222, callee: ?, Symbol(Symbol.iterator): ?]
1.3 剩余rest參數(shù)
ES6中引用了rest parameter,可以將不定數(shù)量的參數(shù)放入到一個(gè)數(shù)組中:
- 如果最后一個(gè)參數(shù)是 ... 為前綴的,那么它會(huì)將剩余的參數(shù)放到該參數(shù)中,并且作為一個(gè)數(shù)組
function foo(num1, num2, ...otherNums) { // otherNums數(shù)組 console.log(otherNums) // [111, 222, 333] } foo(20, 30, 111, 222, 333)
那么剩余參數(shù)和arguments有什么區(qū)別呢?
剩余參數(shù)只包含那些沒(méi)有對(duì)應(yīng)形參的實(shí)參,而 arguments 對(duì)象包含了傳給函數(shù)的所有實(shí)參
arguments對(duì)象不是一個(gè)真正的數(shù)組,而rest參數(shù)是一個(gè)真正的數(shù)組,可以進(jìn)行數(shù)組的所有操作
arguments是早期的ECMAScript中為了方便去獲取所有的參數(shù)提供的一個(gè)數(shù)據(jù)結(jié)構(gòu),而rest參數(shù)是ES6中提供并且希望以此來(lái)替代arguments的
注意:剩余參數(shù)必須放到最后一個(gè)位置,否則會(huì)報(bào)錯(cuò)
1.4 純函數(shù)的使用
- 純函數(shù)的概念:
- 確定的輸入一定產(chǎn)生確定的輸出
- 執(zhí)行過(guò)程中不能副作用
- 副作用是指在執(zhí)行一個(gè)函數(shù)時(shí),除了返回函數(shù)值之外,還對(duì)調(diào)用函數(shù)產(chǎn)生了附加的影響,比如修改了全局變量,修改參數(shù)或者改變外部的存儲(chǔ)
- 實(shí)際開(kāi)發(fā)中應(yīng)用:
- React中就要求無(wú)論是函數(shù)還是class聲明一個(gè)組件,這個(gè)組件都必須像純函數(shù)一樣,保護(hù)它們的props不被修改
- 沒(méi)有必要每一個(gè)函數(shù)都是純函數(shù)
數(shù)組的方法中slice就是一個(gè)純函數(shù),不會(huì)修改數(shù)組本身,而splice函數(shù)不是一個(gè)純函數(shù):
slice:slice截取數(shù)組時(shí)不會(huì)對(duì)原數(shù)組進(jìn)行任何操作,而是生成一個(gè)新的數(shù)組
splice:splice截取數(shù)組, 會(huì)返回一個(gè)新的數(shù)組, 也會(huì)對(duì)原數(shù)組進(jìn)行修改
1.5 柯里化的過(guò)程
什么是柯里化
- 只傳遞給函數(shù)一部分參數(shù)來(lái)調(diào)用它,讓它返回一個(gè)函數(shù)去處理剩余的參數(shù)
兩個(gè)案例:
logInfo
// 1.沒(méi)有柯里化的時(shí)候做法 function logInfo(date, type, message) { console.log(`時(shí)間:${date} 類(lèi)型:${type} 內(nèi)容:${message}`) } // // 打印日志 // logInfo("2022-06-01", "DEBUG", "修復(fù)界面搜索按鈕點(diǎn)擊的bug") // // 又修復(fù)了一個(gè)bug // logInfo("2022-06-01", "DEBUG", "修復(fù)了從服務(wù)器請(qǐng)求數(shù)據(jù)后展示的bug") // logInfo("2022-06-01", "DEBUG", "修復(fù)了從服務(wù)器請(qǐng)求數(shù)據(jù)后展示的bug") // logInfo("2022-06-01", "DEBUG", "修復(fù)了從服務(wù)器請(qǐng)求數(shù)據(jù)后展示的bug") // logInfo("2022-06-01", "FEATURE", "增加了商品的過(guò)濾功能") // 2.對(duì)函數(shù)進(jìn)行柯里化: 柯里化函數(shù)的做法 // var logInfo = date => type => message => { // console.log(`時(shí)間:${date} 類(lèi)型:${type} 內(nèi)容:${message}`) // } function logInfo(date) { return function(type) { return function(message) { console.log(`時(shí)間:${date} 類(lèi)型:${type} 內(nèi)容:${message}`) } } } var logToday = logInfo("2022-06-01") var logTodayDebug = logToday("DEBUG") var logTodayFeature = logToday("FEATURE") // 打印debug日志 logTodayDebug("修復(fù)了從服務(wù)器請(qǐng)求數(shù)據(jù)后展示的bug") logTodayDebug("修復(fù)界面搜索按鈕點(diǎn)擊的bug") logTodayDebug("修復(fù)界面搜索按鈕點(diǎn)擊的bug") logTodayDebug("修復(fù)界面搜索按鈕點(diǎn)擊的bug") logTodayDebug("修復(fù)界面搜索按鈕點(diǎn)擊的bug") logTodayFeature("新建過(guò)濾功能") logTodayFeature("新建搜索功能")
makeAdder
function makeAdder(count) { function add(num) { return count + num } return add } // 1.數(shù)字和5相加 var adder5 = makeAdder(5) adder5(10) adder5(15) adder5(18) // 2.數(shù)組和10相加 var adder10 = makeAdder(10) adder10(10) adder10(16) adder10(19)
柯里化優(yōu)勢(shì):
- 函數(shù)的職責(zé)單一
- 函數(shù)的參數(shù)復(fù)用
自動(dòng)柯里化的函數(shù)封裝
// 將一個(gè)普通函數(shù)轉(zhuǎn)化成柯里化函數(shù) function curried(fn) { function curryFn(...args) { // 傳入的參數(shù)大于等于fn的需要的參數(shù)個(gè)數(shù),直接執(zhí)行fn函數(shù) // 否則返回新的函數(shù)繼續(xù)接收參數(shù) if(args.length >= fn.length) { return fn.apply(this, args) } else { // 返回新的函數(shù)并接收參數(shù) return function(...newArgs) { // 遞歸調(diào)用currFn,此處的參數(shù)為上一次傳入的參數(shù)和之后傳入的參數(shù) return curryFn.apply(this, args.concat(newArgs)) } } } return curryFn }
- 注意:函數(shù)柯里化性能并不高(使用到閉包,可能會(huì)導(dǎo)致內(nèi)存泄露)
1.6 組合函數(shù)的使用
- 組合函數(shù)
- 多個(gè)函數(shù)組合在一起, 依次調(diào)用
封裝組合函數(shù)
// 傳入多個(gè)函數(shù),自動(dòng)的將多個(gè)函數(shù)組合在一起依次調(diào)用 function composeFn(...fns) { var length = fns.length // 邊界判斷 if (length <= 0) return for (var fn of fns) { if (typeof fn !== "function") { throw new Error("Expected a function") } } return function (...args) { // 第一個(gè)函數(shù)可能傳入多個(gè)參數(shù) var result = fns[0].apply(this, args) // 之后的函數(shù)依次調(diào)用 for (var i = 1; i < length; i++) { result = fns[i].apply(this, [result]) } return result } }
二、額外知識(shí)
2.1 with
with語(yǔ)句 擴(kuò)展一個(gè)語(yǔ)句的作用域鏈。
var obj = { message: "Hello World" } with (obj) { console.log(message) // Hello World }
不建議使用with語(yǔ)句,因?yàn)樗赡苁腔煜e(cuò)誤和兼容性問(wèn)題的根源
2.2 eval
內(nèi)建函數(shù) eval 允許執(zhí)行一個(gè)代碼字符串
eval是一個(gè)特殊的函數(shù),它可以將傳入的字符串當(dāng)做JavaScript代碼來(lái)運(yùn)行
eval會(huì)將最后一句執(zhí)行語(yǔ)句的結(jié)果,作為返回值
var message = "Hello World" var codeString = `var name = "kobe"; console.log(name); console.log(message); "abc";` var result = eval(codeString) console.log(result) // abc
不建議在開(kāi)發(fā)中使用eval:
eval代碼的可讀性非常的差(代碼的可讀性是高質(zhì)量代碼的重要原則)
eval是一個(gè)字符串,那么有可能在執(zhí)行的過(guò)程中被刻意篡改,那么可能會(huì)造成被攻擊的風(fēng)險(xiǎn)
eval的執(zhí)行必須經(jīng)過(guò)JavaScript解釋器,不能被JavaScript引擎優(yōu)化
2.3 嚴(yán)格模式
- 什么是嚴(yán)格模式?
嚴(yán)格模式是一種具有限制性的JavaScript模式,從而使代碼隱式的脫離了“懶散(sloppy)模式”
支持嚴(yán)格模式的瀏覽器在檢測(cè)到代碼中有嚴(yán)格模式時(shí),會(huì)以更加嚴(yán)格的方式對(duì)代碼進(jìn)行檢測(cè)和執(zhí)行
嚴(yán)格模式對(duì)正常的JavaScript語(yǔ)義進(jìn)行了一些限制:
嚴(yán)格模式通過(guò)拋出錯(cuò)誤來(lái)消除一些原有的 靜默(silent)錯(cuò)誤
嚴(yán)格模式讓JS引擎在執(zhí)行代碼時(shí)可以進(jìn)行更多的優(yōu)化(不需要對(duì)一些特殊的語(yǔ)法進(jìn)行處理)
嚴(yán)格模式禁用了在ECMAScript未來(lái)版本中可能會(huì)定義的一些語(yǔ)法
- 如何開(kāi)啟嚴(yán)格模式:
- 嚴(yán)格模式通過(guò)在文件或者函數(shù)開(kāi)頭使用 use strict 來(lái)開(kāi)啟
// 給整個(gè)script開(kāi)啟嚴(yán)格模式 "use strict" // 給一個(gè)函數(shù)開(kāi)啟嚴(yán)格模式 function foo() { "use strict" }
- 嚴(yán)格模式的限制:
無(wú)法意外的創(chuàng)建全局變量
嚴(yán)格模式會(huì)使引起靜默失敗(silently fail,注:不報(bào)錯(cuò)也沒(méi)有任何效果)的賦值操作拋出異常
嚴(yán)格模式下試圖刪除不可刪除的屬性
嚴(yán)格模式不允許函數(shù)參數(shù)有相同的名稱(chēng)
不允許0的八進(jìn)制語(yǔ)法
在嚴(yán)格模式下,不允許使用with
在嚴(yán)格模式下,eval不再為上層引用變量
嚴(yán)格模式下,this綁定不會(huì)默認(rèn)轉(zhuǎn)成對(duì)象
"use strict" // 1.不會(huì)意外創(chuàng)建全局變量 // function foo() { // message = "Hello World" // } // foo() // console.log(message) // 報(bào)錯(cuò) // 2.發(fā)現(xiàn)靜默錯(cuò)誤 var obj = { name: "kobe" } Object.defineProperty(obj, "name", { writable: false, configurable: false }) // obj.name = "curry" console.log(obj.name) // delete obj.name console.log(obj) // 3.參數(shù)名稱(chēng)不能相同 // function foo(num, num) { // } // 4.不能以0開(kāi)頭 // console.log(0o123) // 0o是ES6新語(yǔ)法可以寫(xiě) // 5.eval函數(shù)不能為上層創(chuàng)建變量 // eval(`var message = "Hello World"`) // console.log(message) // 6.嚴(yán)格模式下, this是不會(huì)轉(zhuǎn)成對(duì)象類(lèi)型的 function foo() { console.log(this) } foo.apply("abc") foo.apply(123) foo.apply(undefined) foo.apply(null) // 獨(dú)立函數(shù)執(zhí)行默認(rèn)模式下, 綁定window對(duì)象 // 在嚴(yán)格模式下, 不綁定全局對(duì)象而是undefined foo()
總結(jié)
到此這篇關(guān)于JavaScript函數(shù)增強(qiáng)及額外知識(shí)的文章就介紹到這了,更多相關(guān)js函數(shù)增強(qiáng)知識(shí)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS 進(jìn)度條效果實(shí)現(xiàn)代碼整理
進(jìn)度條效果實(shí)現(xiàn)代碼,有助于緩解頁(yè)面顯示慢的頁(yè)面,給用戶(hù)一個(gè)等待時(shí)間的效果2011-05-05layui實(shí)現(xiàn)鼠標(biāo)移動(dòng)到單元格上顯示數(shù)據(jù)的方法
今天小編就為大家分享一篇layui實(shí)現(xiàn)鼠標(biāo)移動(dòng)到單元格上顯示數(shù)據(jù)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09淺談JavaScript的自動(dòng)垃圾收集機(jī)制
本文主要對(duì)JavaScript的自動(dòng)垃圾收集機(jī)制進(jìn)行簡(jiǎn)要分析,并介紹了垃圾收集的方式:標(biāo)記清除(mark-and-sweep)和引用計(jì)數(shù)(reference counting),需要的朋友一起來(lái)看下吧2016-12-12微信小程序動(dòng)態(tài)設(shè)置圖片大小的方法
這篇文章主要介紹了微信小程序動(dòng)態(tài)設(shè)置圖片大小的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-11-11微信小程序使用swiper組件實(shí)現(xiàn)層疊輪播圖
這篇文章主要為大家詳細(xì)介紹了微信小程序使用swiper組件實(shí)現(xiàn)層疊輪播圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11原生JavaScript實(shí)現(xiàn)輪播圖效果
這篇文章主要為大家詳細(xì)介紹了原生JavaScript實(shí)現(xiàn)輪播圖效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09