手写 call函数
封装:给所有函数的原型都添加上一个hycall方法
Function.prtotype.hycall=function(thisArg,...args){
这个this是隐式调用 指向的是谁调用了hycall方法
let funFoo=this
防止传入的非对象的类型时转换成对象类型
thisArg=thisArg?Object(thisArg):window
传入绑定this
thisArg.funFoo=funFoo
调用这个函数 如果有结果返回结果
let result = thisArg.funFoo(...args)
return result
}
function foo(num1,num2){
console.log('foo',this)
console.log(num1,num2)
}
foo.hycall({name:'foo'},10,20,30)
手写bind方法
Function.prototype.hybind = function (thisArg, ...args) {
var funFoo = this
function proxyFun(...arrgs) {
thisArg = thisArg ? Object(thisArg) : window
thisArg.funFoo = funFoo
var finalArgs = [...arrgs, ...args]
var result = thisArg.funFoo(...finalArgs)
return result
}
return proxyFun
}
arguments 方法中的参数类数组 他拥有数组特性 length 索引值 但是没有数组上面的方法 将数组变成array 1.自己通过for循环遍历追加数组
实现一个数组的slice
// arr.slice(1,3)
// Array.prototype.slice = function (start, end) {
// console.log(this)
// var arr = this
// start=start||0
// end=end||arr.length
// var newArray = []
// for (var i = start; i < end; i++) {
// newArray.push(arr[i])
// }
// return newArray
// }
// // 2.1
// var arrArguments=Array.prototype.slice.call(arguments)
// // 2.2
// var arrArguments=[].slice.call(arguments)
// // 2.3
// var arrArguments=Array.from(arguments)
// // 2.4
// var arrArguments=[...arguments]
如果在箭头函数中 arguments本身是没有的 需要从上层作用域找 在js中全局没有arguments 在node中是有arguments 因为在node是通过模块包裹一个函数 执行了一个call方法
柯里化
纯函数
- react中组件被要求像是一个纯函数(因为还有class组件)redux中也有一个reducer的概念 也要求是一个纯函数(Pure Function) 概念
- 此函数在相同的输入值时,需产生相同的输出(在任何情况下给这个函数传入相同的参数 返回都是相同的return)
- 函数的输出和输入意外的其他隐藏信息或状态无关 也和I/O设备产生的外部输出无关 (函数外部变量控制输出的点)
- 该函数不能有语义上可观察的函数副作用,eg:触发事件,使输出设备设备输出,改变输出值意外的内容 总结
- 确定的输入一定会产生相对应的确定的输出
- 函数在执行过程中 不能产生任何副作用 不能修改函数入参以及全局变量 副作用 在执行一个函数时,除了返回函数值以外,还对调用函数产生了附加的影响,eg:修改了全局变量 修改传入参数或者改变外部的存储(localStorange) slice 截取数组 并且不会修改原函数 没有产生副作用 是个纯函数 splice 截取函数 但是会修改原函数 所以不是个纯函数
纯函数的优势 可以安心的编写和安心的使用 只关心这个函数的参数和返回值就可以 你在写的时候保证了函数的纯度,只是单纯实现自己的业务逻辑即可,不需要关心传入的内容是如何获得的或 者依赖其他的外部变量是否已经发生了修改; 你在用的时候,你确定你的输入内容不会被任意篡改,并且自己确定的输入,一定会有确定的输出; React中就要求我们无论是函数还是class声明一个组件,这个组件都必须像纯函数一样,保护它们的props不被修改:
柯里化
把接受多个参数的函数 变成一个单一参数(最初函数的第一个函数)的函数 并且返回接受雨下的参数 返回结果的函数技术 只传递函数的一部分参数来调用它,让它返回一个函数出处理剩下的多余参数
function(m,n,y){
console.log(m+n+y)
}
// 变成下面的代码的过程叫做柯里化
function foo(m){
return function(n){
return function(y){
console.log(m+n+y)
}
}
}
// 简化柯里化代码 箭头函数
var sum =x => y => z =>{
return x+y+z
}
var sum =x => y => z => x+y+z
foo(1)(2)(3)
在函数式编程中,我们其实往往希望一个函数处理的问题尽可能的单一,而不是将一大堆的处理过程交给一个 函数来处理; **那么我们是否就可以将每次传入的参数在单一的函数中进行处理,处理完后在下一个函数中再使用处理后的结果; **
// 封装一个柯里化代码 把普通函数转换成柯里化函数
function add(x, y, z) {
console.log(x + y + z)
}
function hyCurring(fn) {
return function (...args) {
// 判断所需参数和当前参数是否一致 如果一致直接返回函数
if (args.length >= fn.length) {
return fn.call(this, ...args)
} else {
return function (...args2) {
// 接受下一个参数 合并参数进行递归
return hyCurring(fn).apply(this, [...args2, ...args])
}
}
}
}
var hyCurring1 = hyCurring(add)
hyCurring1(19)(20)(2)
组装函数
比如我们现在需要对某一个数据进行函数的调用**,执行两个函数fn1和fn2**,这两个函数是依次执行的; 那么如果每次我们都需要进行两个函数的调用,操作上就会显得重复; 那么是否可以将这两个函数组合起来,自动依次调用呢? 这个过程就是对函数的组合,我们称之为 组合函数(Compose Function);
return Number(n) + 2
}
function double(m) {
return m * 2
}
function compose(...args) {
var length = args.length
for (var i = 0; i < length; i++) {
if (typeof args[i] !== 'function') {
throw new TypeError('请传入函数')
}
}
return function (...args2) {
var index = 0
// 执行第一次调用函数的结果
var result = length ? args[index].call(this, args2) : args2
console.log(result)
while (++index < length) {
result = args[index].call(this, result)
}
return result
}
}
var resultFun = compose(add, double)
console.log(resultFun(2))