一、沙箱模式
-
利用了 函数内 “间接” 的返回了一个函数
-
外部函数返回了一个对象,这个对象内书写多个函数
function outer() {
//1.放置一些外部函数的私有变量
let a = 0
let b = 999
// 2.对象内部放置若干个函数
const obj = {
getA: function () {
return a
},
setA: function (val) {
a = val
},
getB() {
return b
},
setB(val) {
b = val
}
}
// 3.将对象返回到函数外
return obj
}
//得到函数内部的对象,这个对象内部有多个操作函数
const res = outer()
// 得到函数内部的私有变量 a
const winA = res.getA()
// 修改函数内部的私有变量 a
res.setA(winA + 1)
console.log(res.getA())
二、沙箱模式语法糖
语法糖:在不影响功能的情况下,给我们提供了一些更简单的操作方式
- 其实就是利用
getter和setter帮助我们简化了一些操作与代码
// 语法糖版
function outer() {
let a = 1
return {
get a() {
return a
},
set a(val) {
a = val
}
}
}
const res = outer()
console.log(res.a)
res.a = 999
console.log(res.a)
// 普通版沙箱模式
// function outer() {
// let a = 1
// return {
// getA() {
// return a
// },
// setA(val) {
// a = val
// }
// }
// }
// const res = outer()
// res.setA(99)
// console.log(res.getA()) //99
三、函数的柯里化
柯里化函数:一个函数接收多个参数能够完成功能,柯里化函数就是将这一个函数拆分成两个函数,每个函数都只能接收一个参数,然后完成的功能相同。
//需求:使用正则完成一个文本匹配
// 基础版
// const reg = /^\w{6, 12}$/
// const str = '12345'
// console.log(reg.test(str))
// 优化版
// function testStr(fnReg, fnStr) {
// const reg = fnReg
// const str = fnStr
// console.log(reg.test(str))
// }
// testStr(/^\d{5,8}$/, '12345')
// testStr(/^\d{5,8}$/, '54321')
// testStr(/^\d{5,8}$/, 'qwer')
//柯里化函数
function fn(fnReg) { //外层函数,负责接收正则
return function (fnStr) { //内层函数,负责接收字符串,并完成正则校验
console.log(fnReg.test(fnStr)) //只有console.log才会向控制台打印内容
return fnReg.test(fnStr) //将校验结果返回出去给外部代码使用
}
}
const testNum = fn(/^\d{5,8}$/)
// console.log(testNum)
testNum('1234')
testNum('4321')
testNum('123')
const testName = fn(/^\w{6,12}$/)
testName('qwertyui')
四、函数的柯里化封装
函数柯里化内:
-
外层函数:收集参数
-
内层函数:负责处理功能
-
功能:拼接地址栏字符串
传输协议: http https
域名: 127.0.0.1 localhost
端口号:0~65535 7777 808
地址: /a /a/b.html /index.html
普通版
// 普通版
// function fn(a, b, c, d) {
// return a + '://' + b + ':' + c + d
// }
// fn('http', '127.10.11.12', '8080', '/index.html')
// fn('http', '127.10.11.12', '7777', '/index.html')
// fn('http', '127.10.11.12', '7777', '/a.html')
// fn('http', '127.10.11.12', '7777', '/b.html')
// fn('http', '127.10.11.12', '7777', '/c.html')
柯里化版
// 柯里化版
function fn(a, b, c, d) {
// console.log(fn.length)
return a + '://' + b + ':' + c + d
}
// fn()
function curry(callback, ...arg) { //外层函数:负责接收参数
// console.log('callback', callback)
// console.log('arg', arg)
/**
* ?curry 函数需要接收两个参数
* ? callback : 当参数传递足够时需要执行的参数
* ? arg: 接收后续这个参数传递的所有实参(以数组的形式存储)
*/
return function (..._arg) { //内层函数:负责处理功能
_arg = [...arg, ..._arg] //把所有参数放在一个数组中,方便统一维护与管理
// if('当前接收参数的数量' === 'fn函数需要的参数数量'){
// '执行fn函数'
// }
// else{
// '此时参数 数量不满足函数要求,需要继续收集参数'
// }
if (_arg.length === callback.length) {
return callback(..._arg)
}
else {
return curry(callback, ..._arg)
}
}
}
// let newFn = curry(fn, 'http', '127.0.0.1', '8080', '/index.html')
// console.log(newFn())
// let newFn = curry(fn, 'http')
// const newFn2 = newFn('127.0.01', '8080')
// const newFn3 = newFn('/index.html')
// console.log(newFn2)
const newFn = curry(fn)
const newFn2 = newFn('https')
const newFn3 = newFn2('127.0.0.1')
const newFn4 = newFn3('7777')
const newFn5 = newFn4('/index/html')
console.log(newFn5)
五、函数的防抖节流
1.节流
-
事件在执行时,第一次开始执行时,在结束之前或者在指定时间之前,无法触发下一次
-
除非等到第一次执行结束,或者在指定时间到达后,才可以进行下一次
html
<input type="text" class="inp">
JS
const inp = document.querySelector('.inp')
// 0.基础版
// inp.oninput = function () {
// console.log(this.value)
// }
// 1.节流
// let flag = true
// inp.oninput = function () {
// if (flag === false) return
// flag = false
// setTimeout(() => {
// flag = true
// console.log(this.value)
// }, 300)
// }
// 2.扩展 :自执行函数
// function fn() {
// console.log('我是一个普通函数fn')
// }
// fn()
// ; (function fn(num) {
// console.log('我是一个普通函数fn', num)
// })(99)
// 2.节流的优化
// let flag = true
inp.oninput = (function (flag) { //当前这个函数会立即执行,然后返回一个函数给到inp.oninput
// console.log(flagF) //true
return function fn() {
//使用flag的时候会先在当前作用域找,没找到,然后去上层作用域(自执行函数内)找,在这里找到了形参flag,初始值为true
if (flag === false) return
flag = false
setTimeout(() => {
flag = true
console.log(this.value)
}, 300)
}
})(true)
2.防抖
- 事件在开始执行时,如果快速触发了第二次,那么第二次会取代第一次,只会执行最后一次
html
<input type="text" class="inp">
JS
const inp = document.querySelector('.inp')
// 0.基础版
// inp.oninput = function () {
// console.log(this.value)
// }
// 2.防抖
// let timer = 0
// inp.oninput = function () {
// clearInterval(timer)
// timer = setTimeout(() => {
// console.log(this.value)
// }, 300)
// }
//3.自执行函数
// let timer = 0
inp.oninput = (function (timer) {
return function () {
clearInterval(timer)
timer = setTimeout(() => {
console.log(this.value)
}, 300)
}
})(0)
扩展:自执行函数
-
自执行函数需要在代码最前面添加一个分号,用于和上一行代码起到一个分割作用
-
自执行函数如果需要传参,将实参书写在第二个小括号内即可