JavaScript函數(shù)增強以及額外知識
一、函數(shù)增強
1.1 函數(shù)對象的屬性
JavaScript中函數(shù)也是一個對象,那么對象中就可以有屬性和方法。
name:一個函數(shù)的名字我們可以通過name來訪問
length:屬性length用于返回函數(shù)參數(shù)的個數(shù)
- 注意:rest參數(shù)是不參與參數(shù)的個數(shù)的
var bar = function(m, n, ...others) { } console.log(bar.length) // 2
1.2 arguments
arguments 是一個對應(yīng)于傳遞給函數(shù)的參數(shù)的類數(shù)組(array-like)對象
注意:array-like意味著它不是一個數(shù)組類型,而是一個對象類型:
擁有數(shù)組的一些特性,比如說length,比如可以通過index索引來訪問
沒有數(shù)組的一些方法,比如filter、map等
arguments轉(zhuǎn)數(shù)組
遍歷arguments,添加到一個新數(shù)組中
調(diào)用數(shù)組slice函數(shù)的apply方法
ES6中的兩個方法[].slice.apply(arguments) Array.prototype.slice.apply(arguments)
- Array.from
- […arguments]
- 特別注意:箭頭函數(shù)不綁定arguments
- 在箭頭函數(shù)中使用arguments會去上層作用域查找
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ù)放入到一個數(shù)組中:
- 如果最后一個參數(shù)是 ... 為前綴的,那么它會將剩余的參數(shù)放到該參數(shù)中,并且作為一個數(shù)組
function foo(num1, num2, ...otherNums) { // otherNums數(shù)組 console.log(otherNums) // [111, 222, 333] } foo(20, 30, 111, 222, 333)
那么剩余參數(shù)和arguments有什么區(qū)別呢?
剩余參數(shù)只包含那些沒有對應(yīng)形參的實參,而 arguments 對象包含了傳給函數(shù)的所有實參
arguments對象不是一個真正的數(shù)組,而rest參數(shù)是一個真正的數(shù)組,可以進行數(shù)組的所有操作
arguments是早期的ECMAScript中為了方便去獲取所有的參數(shù)提供的一個數(shù)據(jù)結(jié)構(gòu),而rest參數(shù)是ES6中提供并且希望以此來替代arguments的
注意:剩余參數(shù)必須放到最后一個位置,否則會報錯
1.4 純函數(shù)的使用
- 純函數(shù)的概念:
- 確定的輸入一定產(chǎn)生確定的輸出
- 執(zhí)行過程中不能副作用
- 副作用是指在執(zhí)行一個函數(shù)時,除了返回函數(shù)值之外,還對調(diào)用函數(shù)產(chǎn)生了附加的影響,比如修改了全局變量,修改參數(shù)或者改變外部的存儲
- 實際開發(fā)中應(yīng)用:
- React中就要求無論是函數(shù)還是class聲明一個組件,這個組件都必須像純函數(shù)一樣,保護它們的props不被修改
- 沒有必要每一個函數(shù)都是純函數(shù)
數(shù)組的方法中slice就是一個純函數(shù),不會修改數(shù)組本身,而splice函數(shù)不是一個純函數(shù):
slice:slice截取數(shù)組時不會對原數(shù)組進行任何操作,而是生成一個新的數(shù)組
splice:splice截取數(shù)組, 會返回一個新的數(shù)組, 也會對原數(shù)組進行修改
1.5 柯里化的過程
什么是柯里化
- 只傳遞給函數(shù)一部分參數(shù)來調(diào)用它,讓它返回一個函數(shù)去處理剩余的參數(shù)
兩個案例:
logInfo
// 1.沒有柯里化的時候做法 function logInfo(date, type, message) { console.log(`時間:${date} 類型:${type} 內(nèi)容:${message}`) } // // 打印日志 // logInfo("2022-06-01", "DEBUG", "修復界面搜索按鈕點擊的bug") // // 又修復了一個bug // logInfo("2022-06-01", "DEBUG", "修復了從服務(wù)器請求數(shù)據(jù)后展示的bug") // logInfo("2022-06-01", "DEBUG", "修復了從服務(wù)器請求數(shù)據(jù)后展示的bug") // logInfo("2022-06-01", "DEBUG", "修復了從服務(wù)器請求數(shù)據(jù)后展示的bug") // logInfo("2022-06-01", "FEATURE", "增加了商品的過濾功能") // 2.對函數(shù)進行柯里化: 柯里化函數(shù)的做法 // var logInfo = date => type => message => { // console.log(`時間:${date} 類型:${type} 內(nèi)容:${message}`) // } function logInfo(date) { return function(type) { return function(message) { console.log(`時間:${date} 類型:${type} 內(nèi)容:${message}`) } } } var logToday = logInfo("2022-06-01") var logTodayDebug = logToday("DEBUG") var logTodayFeature = logToday("FEATURE") // 打印debug日志 logTodayDebug("修復了從服務(wù)器請求數(shù)據(jù)后展示的bug") logTodayDebug("修復界面搜索按鈕點擊的bug") logTodayDebug("修復界面搜索按鈕點擊的bug") logTodayDebug("修復界面搜索按鈕點擊的bug") logTodayDebug("修復界面搜索按鈕點擊的bug") logTodayFeature("新建過濾功能") 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ù)的參數(shù)復用
自動柯里化的函數(shù)封裝
// 將一個普通函數(shù)轉(zhuǎn)化成柯里化函數(shù) function curried(fn) { function curryFn(...args) { // 傳入的參數(shù)大于等于fn的需要的參數(shù)個數(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ù)柯里化性能并不高(使用到閉包,可能會導致內(nèi)存泄露)
1.6 組合函數(shù)的使用
- 組合函數(shù)
- 多個函數(shù)組合在一起, 依次調(diào)用
封裝組合函數(shù)
// 傳入多個函數(shù),自動的將多個函數(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) { // 第一個函數(shù)可能傳入多個參數(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 } }
二、額外知識
2.1 with
with語句 擴展一個語句的作用域鏈。
var obj = { message: "Hello World" } with (obj) { console.log(message) // Hello World }
不建議使用with語句,因為它可能是混淆錯誤和兼容性問題的根源
2.2 eval
內(nèi)建函數(shù) eval 允許執(zhí)行一個代碼字符串
eval是一個特殊的函數(shù),它可以將傳入的字符串當做JavaScript代碼來運行
eval會將最后一句執(zhí)行語句的結(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
不建議在開發(fā)中使用eval:
eval代碼的可讀性非常的差(代碼的可讀性是高質(zhì)量代碼的重要原則)
eval是一個字符串,那么有可能在執(zhí)行的過程中被刻意篡改,那么可能會造成被攻擊的風險
eval的執(zhí)行必須經(jīng)過JavaScript解釋器,不能被JavaScript引擎優(yōu)化
2.3 嚴格模式
- 什么是嚴格模式?
嚴格模式是一種具有限制性的JavaScript模式,從而使代碼隱式的脫離了“懶散(sloppy)模式”
支持嚴格模式的瀏覽器在檢測到代碼中有嚴格模式時,會以更加嚴格的方式對代碼進行檢測和執(zhí)行
嚴格模式對正常的JavaScript語義進行了一些限制:
嚴格模式通過拋出錯誤來消除一些原有的 靜默(silent)錯誤
嚴格模式讓JS引擎在執(zhí)行代碼時可以進行更多的優(yōu)化(不需要對一些特殊的語法進行處理)
嚴格模式禁用了在ECMAScript未來版本中可能會定義的一些語法
- 如何開啟嚴格模式:
- 嚴格模式通過在文件或者函數(shù)開頭使用 use strict 來開啟
// 給整個script開啟嚴格模式 "use strict" // 給一個函數(shù)開啟嚴格模式 function foo() { "use strict" }
- 嚴格模式的限制:
無法意外的創(chuàng)建全局變量
嚴格模式會使引起靜默失敗(silently fail,注:不報錯也沒有任何效果)的賦值操作拋出異常
嚴格模式下試圖刪除不可刪除的屬性
嚴格模式不允許函數(shù)參數(shù)有相同的名稱
不允許0的八進制語法
在嚴格模式下,不允許使用with
在嚴格模式下,eval不再為上層引用變量
嚴格模式下,this綁定不會默認轉(zhuǎn)成對象
"use strict" // 1.不會意外創(chuàng)建全局變量 // function foo() { // message = "Hello World" // } // foo() // console.log(message) // 報錯 // 2.發(fā)現(xiàn)靜默錯誤 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ù)名稱不能相同 // function foo(num, num) { // } // 4.不能以0開頭 // console.log(0o123) // 0o是ES6新語法可以寫 // 5.eval函數(shù)不能為上層創(chuàng)建變量 // eval(`var message = "Hello World"`) // console.log(message) // 6.嚴格模式下, this是不會轉(zhuǎn)成對象類型的 function foo() { console.log(this) } foo.apply("abc") foo.apply(123) foo.apply(undefined) foo.apply(null) // 獨立函數(shù)執(zhí)行默認模式下, 綁定window對象 // 在嚴格模式下, 不綁定全局對象而是undefined foo()
總結(jié)
到此這篇關(guān)于JavaScript函數(shù)增強及額外知識的文章就介紹到這了,更多相關(guān)js函數(shù)增強知識內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
layui實現(xiàn)鼠標移動到單元格上顯示數(shù)據(jù)的方法
今天小編就為大家分享一篇layui實現(xiàn)鼠標移動到單元格上顯示數(shù)據(jù)的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-09-09