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

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

  • 1.函数柯里化
    • 1.1 确定参数的函数柯里化
    • 1.2参数不确定的函数柯里化
    • 1.3 用法
      • 1.3.1 给setTimeout传递进来的函数添加参数
  • 2.回调解决异步多线程

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 确定参数的函数柯里化

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()
})

记录一下,持续修改更进

你可能感兴趣的:(学习,javascript,开发语言)