函数柯里化
- 函数的科里化 就是将一个可以接收多个参数的函数改装为只能接收一个参数 然后多次调用的函数
- 利用函数闭包延长外部函数的参数的使用时间
函数柯里化封装
- 思路
- 外层函数负责接收参数
- 内层函数在参数接收到指定数量的时候将参数传递给功能函数
- 同时判断
参数的数量是否达到要求
(函数名.length)可以获取到函数的形参
- js函数的
constructor属性中有length属性 该属性为函数的形参数量
function my(a, c, f, g) {
console.log(arguments.length)
}
my(1,2,2,3)
console.log(my.prototype)
- 而
arguments.length为调用时传递实参的数量
- 科里化的步骤
function myAdd(a, b, c, d) {
return a + b + c + d
}
- 所以 我们可以封装一个函数来保证传递的参数一定达到要求
- 随便写一个吧 (约定首个参数为功能函数且可以接收多个形参)
function myCurring(callback, ...arg) {
return (...Arg) => {
Arg = [...arg,...Arg]
if (callback.length === 4) {
return callback(...Arg)
} else {
return myCurring(callback, ...Arg)
}
}
}
let s = myCurring(myAdd,1)
console.log(s(2, 3, 4))
函数的防抖与节流
- 节流:在一定时间内快速触发某一事件 在规定时间内只能触发一次 上一次事件结束之后才可以继续触发
- 实现思路:
- 需要一个初始变量 假设为
flag = true
- 在事件开始时判断其是否为
false是则返回中断函数 同时将flag的值赋值为false
- 事件结束时将
flag重新赋值为 true
- 例
<style>
div{
height: 100px;
width: 100px;
background-color: pink;
}
</style>
<body>
<div></div>
<script>
let flag = true
let oDiv = document.querySelector('div')
oDiv.onclick = function (e) {
if (!flag) return
flag = false
let num = 5
let timer = setInterval(() => {
num--
this.innerHTML = num
if(num == 0){
clearInterval(timer)
flag = true
}
},1000)
}
</script>
</body>
数据劫持
- 数据劫持 顾名思义 就是劫持一个数据
- 方法(语法):
Object.defineProperty(劫持对象(非人),要劫持的属性,{配置劫持方法})
- 内部的一些劫持方法
value 访问该劫持属性是 会获取到的值
writable 决定当前属性是否能被修改
enumerable 决定当前属性能否被枚举(遍历)
getter 是一个函数 当访问这个属性时会执行的函数
setting 函数 当要修改这个属性的时候会调用的函数
getter 不能和 value writable同时使用
- 例(语法)
Object.defineProperty(obj, 'age', {
enumerable: true,
get() {
return 'qwer'
},
set(val) {
console.log('你当前想要修改这个 age 属性, 修改的值 是: ', val)
}
})
模拟数据劫持 + 渲染
- 实现数据驱动视图(视图与数据更新保持同步)
- 实现原理
setting函数在每一设置属性时 都会被调用 所以在该函数内渲染界面(每次修改都会重新渲染界面)
<body>
<div></div>
<script>
let oDiv = document.querySelector('div')
let obj = {
a:10
}
const res = {}
Object.defineProperty(res,a,{
get () {
return obj.a
},
set (val) {
obj.a = val
Odiv.innerText = res.a
}
})
Odiv.innerText = res.a
res.a = 1100
</script>
</body>
数据劫持升级
- 将上一步操作进行封装(模仿框架的0.0000001%功能)
- 满足部分功能
- 语法
- 升级版
语法: Object.defineProperties(到那个对象, {
属性1: 配置项,
属性2: 配置项
})
for (let k in obj) {
Object.defineProperties(obj, {
['_' + k]: {
value: obj[k],
writable: true
},
[k]: {
get () {
return obj['_' + k]
},
set(val) {
obj['_' + k] = val
}
}
})
}
数据代理
- 数据代理 类似一个第三方 好比销售代理 我随时可获取你的产品 我帮你销售就行 你只管更新产品
Proxy(劫持对象,配置项) 接收一个参数 和一个配置项 target p
- Proxy内的get方法接收两个参数
target p
target为当前代理对象 P为该对象的每一个key 也就是说 Proxy自带遍历
- p为遍历后的每一个key
- set方法接收第三个参数 `set(target, p, value)
const obj = {
name: 'QF001',
age: 18
}
const res = new Proxy(obj, {
get (target, p) {
return target[p]
},
set (target, p, val) {
target[p] = val
console.log('你想要修改某一个属性')
return true
}
})
res.age = 99
obj.abc = 999
res.abc = 666
console.log(res)