大綱:
- 函數(shù)柯里化
- 偏函數(shù)
- 正則截取query部分
- ts
前置知識(shí):
- 函數(shù)的參數(shù)
- 函數(shù)的 length 屬性冬殃,返回函數(shù)預(yù)期的參數(shù)個(gè)數(shù) ---------------------- (形參)
- 函數(shù)內(nèi)的 arguments對(duì)象 包含了函數(shù)運(yùn)行時(shí)的所有參數(shù) ---------(實(shí)參)
- 類數(shù)組對(duì)象轉(zhuǎn)換成數(shù)組
- [].slice.call(類似數(shù)組的對(duì)象)
- [].slice.apply(類似數(shù)組的對(duì)象)
- Array.prototype.slice.call(類似數(shù)組的對(duì)象)
- Array.from()
- Function.prototype.apply()
- apply的第一個(gè)參數(shù)是要綁定的對(duì)象,當(dāng)是null和undefined時(shí)募寨,指的是全局對(duì)象window
- concat ------------------- concat不會(huì)改變?cè)瓟?shù)組
- concat用于多個(gè)數(shù)組的拼接族展,將新數(shù)組的成員拼接到舊數(shù)組的尾部,返回一個(gè)新數(shù)組
- 注意:concat不會(huì)改變?cè)瓟?shù)組
- 偏函數(shù)和函數(shù)柯里化概念
偏函數(shù):是固定一個(gè)或多個(gè)參數(shù)拔鹰,產(chǎn)生另一個(gè)較小元的函數(shù)n元函數(shù) => 轉(zhuǎn)換成n-x元函數(shù)
柯里化:將多個(gè)參數(shù)函數(shù)轉(zhuǎn)化成單一參數(shù)函數(shù)------------------n元函數(shù) => 轉(zhuǎn)換成n個(gè)一元函數(shù)
- 偏函數(shù)(partial application)
partial:是部分的意思
- 柯里化
currying
- rest參數(shù)
- rest參數(shù):
...變量名
用來獲取函數(shù)的多余參數(shù) -
...變量名
變量名是一個(gè)數(shù)組
(1)函數(shù)柯里化
- 函數(shù)柯里化:就是將一個(gè)
多個(gè)參數(shù)的函數(shù)
仪缸,轉(zhuǎn)化成一系列一個(gè)參數(shù)的函數(shù)
的過程 - 柯里化, 即 Currying 的音譯。
function x(a,b,c) {
console.log([].slice.call(arguments))
console.log([].slice.apply(arguments))
console.log(Array.prototype.slice.apply(arguments))
console.log(Array.from(arguments))
}
x(1,2,3,4,5)
x.length --------------------------- 函數(shù)形參的個(gè)數(shù) 3
x內(nèi)部的arguments.length -------------------- 函數(shù)的實(shí)參的集合 5
柯里化階段一
需求:將add(a,b,c) 轉(zhuǎn)化成 curryAdd(a)(b)(c)
缺點(diǎn):只能處理三個(gè)參數(shù)的情況列肢,不能處理任意多個(gè)參數(shù)的情況
function add(a,b,c) {
return a+b+c
}
function curryAdd(a) {
return function(b) {
return function(c) {
return a+b+c
}
}
}
柯里化階段二
需求:處理任意多個(gè)參數(shù)相加
缺點(diǎn):
1. 處理相加邏輯的代碼恰画,只是在沒有參數(shù)時(shí)才會(huì)執(zhí)行,其他部分都在處理怎么收集所有參數(shù)
2. 所以出來相加邏輯的代碼瓷马,可以通過傳參的形式來調(diào)用拴还,執(zhí)行相加邏輯
function curryAdd() {
let params_arr = [] //-------------------- 定義一個(gè)用于收集參數(shù)的數(shù)組
const closure = function() { // ------------ 定義一個(gè)閉包
const args = Array.prototype.slice.apply(arguments) //------------ 收集每次調(diào)用的參數(shù),一次可能有多個(gè)
if (args.length) {
params_arr = params_arr.concat(args)
// 用concat是因?yàn)榭梢砸淮握{(diào)用欧聘,一次傳了多個(gè)參數(shù)
// 注意concat不會(huì)改變?cè)瓟?shù)組片林,返回值是拼接過后的新數(shù)組
return closure
} // 如果參數(shù)存在,就收集到數(shù)組怀骤,并且返回閉包费封,繼續(xù)判斷存不存在參數(shù)
params_arr.reduce((total, current) => total + current) // 如果參數(shù)已經(jīng)不存在了,就相加所有尺寸參數(shù)
}
return closure // -------------------------- 返回一個(gè)閉包
}
const fn = curryAdd()
const res = fn(1)(2)(3)(4)() // 10-------------注意需要最后一個(gè)調(diào)用一個(gè)空參數(shù)的閉包
const res2 = fn(1)(2)(3)(4, 10)() // 20
柯里化階段三
缺點(diǎn):
1. 函數(shù)中在判斷是否傳入?yún)?shù)晒喷,沒有了再執(zhí)行相加
2. 也就是說孝偎,最后一次一定要執(zhí)行一次空參數(shù)的回調(diào)
3. 所以更合理的方式:就是通過函數(shù)可以接收參數(shù)的總數(shù)來判斷
function add(arr) {
return arr.reduce((total, current) => total + current)
}
function curryAdd(fnAdd) {
let params_arr = [] //-------------------- 定義一個(gè)用于收集參數(shù)的數(shù)組
const closure = function(...args) { // args是一個(gè)數(shù)組
if (args.length) {
params_arr = params_arr.concat(args) // 用concat是因?yàn)槊看握{(diào)用访敌,都可以傳多個(gè)參數(shù)
return closure
} // 如果參數(shù)存在凉敲,就收集到數(shù)組,并且返回閉包,繼續(xù)判斷存不存在參數(shù)
// 如果參數(shù)不存在爷抓,執(zhí)行傳入的函數(shù)
return fnAdd(params_arr)
}
return closure // -------------------------- 返回一個(gè)閉包
}
const go = curryAdd(add)
const res = go(1)(2,3)(4)()
console.log(res, 'res')
柯里化階段四
function add(x,y,z,m) {
return x+y+z+m
}
function curryAdd (fnAdd) {
let params_arr = []
const maxLength = fnAdd.length // 形參的長(zhǎng)度
console.log(maxLength, 'maxLength')
const closure = function () {
params_arr = params_arr.concat([].slice.apply(arguments))
// 執(zhí)行一次閉包就收集一個(gè)參數(shù)势决,而不是判斷完再收集
if (params_arr.length < maxLength) {
// 如果參數(shù)數(shù)組中收集到的參數(shù)長(zhǎng)度 小于 函數(shù)形參的參數(shù)長(zhǎng)度,執(zhí)行閉包
return closure
}
return fnAdd(...params_arr)
}
return closure
}
const go = curryAdd(add)
const res = go(1,2)(3,4)
console.log(res) //10
https://juejin.im/post/5c677041f265da2de25b7707
http://www.reibang.com/p/fe0d80b04129
https://juejin.im/post/5c932a556fb9a070cd56998e
https://juejin.im/post/5c619de8f265da2d8a559131
(2) 偏函數(shù)
- 將一個(gè)或者多個(gè)參數(shù)固定到一個(gè)函數(shù)蓝撇,產(chǎn)生一個(gè)更小元的函數(shù)
function add (a, b) {
return a + b
}
function partial (fn) {...}
const addPartial = partial(add, 1) // ------------------ 實(shí)現(xiàn)固定一部分參數(shù)1
const res = addPartial(2) // 3 -------------------------- 只傳一部分參數(shù) 2
偏函數(shù)實(shí)現(xiàn)方式一
- bind方法
function add (a, b) {
return a + b
}
function partial () {
let args = Array.prototype.slice.call(arguments)
const fn = args.shift()
return fn.bind(this, ...args)
// ----------- bind方法果复,返回新的函數(shù)
// ----------- 除了第一個(gè)參數(shù),后面的參數(shù)渤昌,是傳給fn的參數(shù)
}
const addPartial = partial(add, 1)
const res = addPartial(2) // 除了固定的參數(shù)虽抄,剩下的參數(shù)在這里傳入
console.log(res, 'res') // 3
偏函數(shù)實(shí)現(xiàn)方法二
function add (a, b, c) {
return a + b + c
}
function partial(fn) {
let params = Array.prototype.slice.call(arguments, 1) // 拿到除取函數(shù)外的其他所有參數(shù),是一個(gè)數(shù)組
const closure = function() {
const currentParams = Array.prototype.slice.call(arguments) // 每次閉包接收的參數(shù)
params = params.concat(currentParams) // 傳入收集參數(shù)的數(shù)組中
console.log(params)
if ( params.length < fn.length ) { // 參數(shù)收集數(shù)組長(zhǎng)度 如果 小于add函數(shù)預(yù)期參數(shù)個(gè)數(shù)時(shí),繼續(xù)收集
return closure
}
return fn.apply(null, params) // 如果等于add預(yù)期參數(shù)時(shí)独柑,停止收集參數(shù)迈窟,執(zhí)行add函數(shù)
}
return closure
}
const addPratial = partial(add, 2)
const res = addPratial(3)(4)
console.log(res, 'res') // 9
https://juejin.im/post/5993a7ea6fb9a0247f4f2d08
正則截取query部分
const str = 'http://www.reibang.com/u/70c8a3b8bb44?name=wu&age=20'
const slice = str.match(/([^?&=]+)=([^?&=]+)/g)
// 全局匹配
// ([^?&=]+) 除去? & = 外的一個(gè)或者多個(gè)字符
console.log(slice) // ["name=wang", "age=20"]
const str = 'http://www.baidu.com/?name=wang&age=20&sex=man#'
const res = str.match(/\?(.+)#/)[1].match(/[^&#]+=[^&#]+/g)
console.log(res)
TS
數(shù)組
數(shù)組的兩種表示方法
let list: number[] = [1, 2, 3];
let list: Array<number> = [1, 2, 3]; -------------- 數(shù)組泛型 Array<類型變量>
null 和 undefined
- null 和 undefined 是所有類型的子類型
- 當(dāng)指定了
--strictNullChecks標(biāo)記
,null和undefined就只能賦值給void和他們各自
never
- never類型是任何類型的子類型
類型斷言 ----------------------------- 相當(dāng)于類型轉(zhuǎn)換
- 類型斷言有兩種形式
- 尖括號(hào)語法
- as語法
1. as語法 ---- 在jsx中只能使用 as
let someValue: any = "this is a string"; -------------------------- 本來 someValue 是 any類型的 變量
let strLength: number = (someValue as string).length; ------------- 被斷言成了字符串類型
接口
- ReadonlyArray<T> ------------ 此數(shù)組不能被修改忌栅,且類型是T類型的數(shù)組
- Array<T> ------------------------- 數(shù)組泛型
- readonly和const的區(qū)別
- const 用于變量
- readonly 用于屬性
函數(shù)類型
interface SearchFunc {
(source: string, subString: string): boolean; --------------- 函數(shù)類型车酣,包含參數(shù)列表和返回值
}
類
- private 不能在聲明他的類的外部訪問
-
參數(shù)屬性
:通過給構(gòu)造函數(shù)參數(shù)前面添加一個(gè)訪問限制符
來聲明- 比如:使用 private 限制一個(gè)參數(shù)屬性,會(huì)聲明并初始化一個(gè)私有成員
-
abstract:是抽象的意思
類型謂詞
- parameterName is Type索绪,parameterName必須來自當(dāng)函數(shù)簽名里的一個(gè)參數(shù)名
typeof類型保護(hù)
類型別名
- 類型別名會(huì)給類型取一個(gè)新名字
- 類型別名和接口很像湖员,當(dāng)可以作用域原始值,聯(lián)合類型瑞驱,元組娘摔,和任何其他任何你需要手寫的類型
- 類型別名不會(huì)新建一個(gè)類型,而是創(chuàng)建了一個(gè)名字钱烟,來引用那個(gè)類型
- 同接口一個(gè)晰筛,類型別名也可以是泛型
- 可以在類型別名的屬性中引用自己
type ------------------------------------------- 聲明一個(gè)類型別名
type Name = string; ---------------------- 類型別名可以作用于原始類型,聯(lián)合類型拴袭,元組读第,或者其他任何需要手寫的類型
type NameResolver = () => string; -------- 函數(shù)類型
type NameOrResolver = Name | NameResolver; ------- 聯(lián)合類型
function getName(n: NameOrResolver): Name {
if (typeof n === 'string') { ----------------- typeof類型保護(hù)
return n;
}
else {
return n();
}
}
type Container<T> = { value: T }; ----------- 類型別名也可以是泛型
接口 vs 類型別名
- 接口創(chuàng)建了一個(gè)姓名字,在任何地方都可以使用拥刻,類型別名不創(chuàng)建新名字(錯(cuò)誤信息就不使用別名)
- 類型別名不能被 extends 和 implements
- 如果你無法通過接口來描述一個(gè)類型怜瞒,并且你需要使用聯(lián)合類型或者元組類型,通常會(huì)使用類型別名
索引類型
- 索引類型查詢操作符般哼,索引訪問操作符
- 索引類型查詢操作符:
keyof T 的結(jié)果表示:T上已知公共屬性名的聯(lián)合
- 索引訪問操作符:
T[K] ------- 就是T中K屬性對(duì)應(yīng)的類型
- 索引類型查詢操作符:
映射類型
- 從就類型中創(chuàng)建新類型的方式
- Keys:是已經(jīng)存在的聯(lián)合類型
- k內(nèi)部會(huì)循環(huán)keys中的屬性
- 最后是:屬性的結(jié)果類型