6.30学习-函数柯里化,回调解决异步多线程

1.函数柯里化

函数柯里化,经常可能就面试的时候听说过,反正一般开发我就很少用到过(自己层次不够吧)。老规矩,先上一段代码

// function isType(value,type) {
//    return Object.prototype.toString.call(value) === `[object ${type}]`;
// }
// console.log(isType([1,2,3],'Array'))
//但是如果第二个参数传成'array','Arary'等,就会判断不是 

function isType(type) {
   return function (value) {
      return Object.prototype.toString.call(value) === `[object ${type}]`;
   }
}
let isArray = isType('Array');
console.log(isArray([1,2,3]))
console.log(isArray(1,2,3))
console.log(isType('Array')([1,2,3]))

上面代码也就是判断变量的类型,但是第一种和第二种的写法不大相同的,第一种写法是一个多个参数的函数,第二个却是变成了单一的参数。其实这就是柯里化。

柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数

上面我们虽然对函数进行了柯里化,但是我们不可能在需要柯里化的时候,都像上面不断地进行函数的嵌套;所以我们通过一个柯里化函数,实现通用的柯里化方法

1.1 确定参数的函数柯里化

原来的文章跨度有点大,补充

// let isArray = currying(isType)(‘Array’);
// let isString = currying(isType)(‘String’);
// console.log(isArray)
// console.log(isArray([1, 2, 3])) //true
// console.log(isArray(‘aaa’)) //false
// console.log(isString([1, 2, 3])) //false
// console.log(isString(‘aaa’)) //true
要实现这个,肯定重要的就在于currying函数

刚开始写的

const currying = (fn) => {
   console.log(fn.length)
   //应该关键就在于如何可以连续的传参吧 这里拿到了要传参的个数
   //肯定也是要返回一个函数的

   return function (...args) {
      let a1 = [...args]
      return function (...args) {
         return fn(...[...a1, ...args])
      }
   }
}

只能说这个例子可以这样写,但是很不通用的。加个参数记录判断下参数的长度

const currying = (fn, arr = []) => {
   let len = fn.length;
   // return function (...args) {
   //    arr = [...arr,...args]
   //    console.log('arr',arr)
   //    if(arr.length < len){
   //       return currying(fn, arr)
   //    }
   //    else{
   //       return  fn(...arr)
   //    }
   // }
   return function (...args) {
      let concatVal = [...arr, ...args]
      //  console.log('arr',concatVal)
      if (concatVal.length < len) {
         return currying(fn, concatVal)
      }
      else {
         return fn(...concatVal)
      }
   }
}
function isType(type, value) {
   return Object.prototype.toString.call(value) === `[object ${type}]`;
}
let isArray = currying(isType)('Array');
let isString = currying(isType)('String');
console.log(isArray)
console.log(isArray([1, 2, 3]))  //true
console.log(isArray('aaa'))  //false
console.log(isString([1, 2, 3]))  //false
console.log(isString('aaa'))  //true

1.2参数不确定的函数柯里化

这里就有个经典的面试题了,实现sum(1,2,3,5)的效果和sum(1,2)(3)(5),sum(1,2,3)(5)一样

function sum() {
   let args = [...arguments];
   let res = function () {
      args.push(...arguments);
      // let result = args.reduce((pre, cur) => pre + cur)
      return res
   }
   res.toString = function(){
      return args.reduce((prev,cur)=>prev+cur)  
  }
   return res
}
console.log(sum(1, 2, 3).toString(), sum(1).toString()) //6 1

console.log(sum(1)(2,5)().toString()) // 8

1.3 用法

用法参考了点击这里跳转

1.3.1 给setTimeout传递进来的函数添加参数

function hello(name) {
    console.log('Hello, ' + name);
}
setTimeout(hello('kangkang'), 3600); //立即执行,不会在3.6s后执行
setTimeout(function() {
    hello('kangkang');
}, 3600); // 3.6s 后执行

当然,在ES5里面,我们也可以使用函数的bind方法,如下所示:

setTimeout(hello.bind(this, 'kangkang'), 3600); // 3.6s 之后执行函数

这样也是非常的方便快捷,并且可以绑定函数执行的上下文.

这里我们讨论函数的柯里化,当然我们这里也可以使用函数的柯里化来达到这个效果:

setTimeout(currying (hello, 'kangkang'), 3600); // 其中currying 是上面已经提及过的

2.回调解决异步多线程

let fs = require('fs');
let person = {}
fs.readFile('./1.txt', 'utf8', function(err,data){
   console.log(data);
   person.name = data
})
fs.readFile('./2.txt', 'utf8', function(err,data){
   console.log(data);
   person.age = data
})
console.log('person',person)

上面这段代码的结果是这样的:
在这里插入图片描述
挺明显的,我们想要拿到的是person {name:‘qiu’,age:‘18’},但是结果却还是个空对象。js中node的readFile方法是异步的,我们的代码也是基于node来运行的。异步是在同步代码后执行的,所以这里打印的的person还是空对象。肯定promise也是可以解决这个问题的,但这里重点讲回调。

let fs = require('fs');
let person = {}
//通过回调
let index = 0
let cb = () => {
   index++;
   if(index == 2){
      console.log('person',person) //person { name: 'qiu', age: '18' }
   }
   // console.log(index)
}
fs.readFile('./1.txt', 'utf8', function(err,data){
   person.name = data
   cb()
})
fs.readFile('./2.txt', 'utf8', function(err,data){
   person.age = data
   cb()
})

可以在读取文件成功后调用函数,再设置个index进行判断结束条件就可以拿到异步结束后的值了。
使用闭包,还可以让代码灵活一点

let fs = require('fs');
let person = {}
function after(index, callback) {
   // index--;   //闭包函数,函数的定义的作用域和函数执行的作用域 不在同一个作用域下
   //闭包是定义在一个函数内部的函数,内层函数可以访问外层函数的局部变量,这些变量被内层函数引用不会被回收,
   //好处是使局部变量拥有更长的生命周期可以用来封装一段逻辑,坏处是闭包常驻内存造成内存泄露。
   return function () {
      index--;
      if (index == 0) {
         callback();
      }
   }
}
let cb = after(2, function () {
   console.log(person)
})
fs.readFile('./1.txt', 'utf8', function (err, data) {
   person.name = data
   cb()
})
fs.readFile('./2.txt', 'utf8', function (err, data) {
   person.age = data
   cb()
})

记录一下,持续修改更进

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值