# study **Repository Path**: yuweiXia/study ## Basic Information - **Project Name**: study - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-04-01 - **Last Updated**: 2023-02-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 关于函数 什么是高阶函数:把函数作为参数或者返回值的一类函数。 #### before函数 ```javascript Function.prototype.before = function(beforeFn){ return ()=>{ beforeFn(); this(); } } function fn(){ console.log('source') } const newFn = fn.before(say=>{ console.log('say'); }); newFn(); ``` AOP(面向切面编程)的主要作用是把一些跟核心业务逻辑模块无关的功能抽离出来,其实就是给原函数增加一层,不用管原函数内部实现 ```javascript * wrappers (injected at creation time) * + + * | | * +-----------------|--------|--------------+ * | v | | * | +---------------+ | | * | +--| wrapper1 |---|----+ | * | | +---------------+ v | | * | | +-------------+ | | * | | +----| wrapper2 |--------+ | * | | | +-------------+ | | | * | | | | | | * | v v v v | wrapper * | +---+ +---+ +---------+ +---+ +---+ | invariants * perform(anyMethod) | | | | | | | | | | | | maintained * +----------------->|-|---|-|---|-->|anyMethod|---|---|-|---|-|--------> * | | | | | | | | | | | | * | | | | | | | | | | | | * | | | | | | | | | | | | * | +---+ +---+ +---------+ +---+ +---+ | * | initialize close | * +-----------------------------------------+ * ``` #### 类型检测 ```javascript function checkType(content,Type){ return Object.prototype.toString.call(content) === `[object ${Type}]` } const flag = checkType('hello','String'); // ----------------------------------- function checkType(Type){ return function(content){ return Object.prototype.toString.call(content) === `[object ${Type}]` } } const flag = checkType('hello','String'); const util = {}; const types = ['String','Number','Boolean']; types.forEach(type=>{ util['is'+type] = checkType(type); }); ``` 函数分步传递参数,将函数拆分成功能更具体化的函数 #### 柯里化函数 ```javascript //笔记里的写法 const currying = (fn,args = []) => { let len = fn.length; return (..._)=>{ let arg = args.concat(_); if(arg.length < len){ return currying(fn,arg); } return fn(...arg); } }; //另外一个写法 // function currying(fn) { // //存储每次调用的时候传入的变量 // const inner = (args = []) => { // //存储每次调用传入的参数 // return args.length >= fn.length? fn(...args): (...userArgs) => inner([...args, ...userArgs]); // //递归返回函数 // }; // return inner(); // } const add = (a, b, c, d, e) => { return a + b + c + d + e; }; let r = currying(add)(1)(2,3)(4,5); console.log(r); ``` 柯里化类型函数 ```javascript const types = ['String','Number','Boolean']; let utils = {} types.forEach(type=>{ utils[`is${type}`] = currying(isType)(type); }) ``` #### after函数的应用 ```javascript const after = (times, callback) => () => { if (--times === 0) { callback(); } }; const newFn = after(3, () => { console.log("ok"); }); ``` #### 发布订阅模式 、 观察者模式 一种一对多的关系,发布者和订阅者是否有关联,观察者模式基于发布订阅模式 ## 异步&事件环 #### 一promise.all原理 ```javascript // 判断是否是promise const isPromise = value =>{ if((typeof value === 'object' && value !== null) ||typeof value === 'function'){ return typeof value.then === 'function' } return false; } Promise.all = function (promises) { return new Promise((resolve,reject)=>{ let arr = []; let i = 0; let processData = (index,data)=>{ arr[index] = data; // 保证返回结果顺序 if(++i === promises.length){ resolve(arr); } } for(let i = 0; i< promises.length;i++){ let current = promises[i]; if(isPromise(current)){ current.then(data=>{ processData(i,data) },reject) }else{ processData(i,current); } } }) } ``` >Promise.all可以解决异步并发问题,并且返回的结果按照调用的顺序进行存储。全部成功后才成功否则执行失败逻辑 #### 二.Promise.race原理 ```javascript Promise.race = function (promises) { return new Promise((resolve, reject) => { // 谁返回的结果最快 就用谁的 for (let i = 0; i < promises.length; i++) { let current = promises[i]; if (isPromise(current)) { current.then(resolve, reject) } else { resolve(current); } } }) ``` >race只采用第一个成功或者失败的结果 ##### 2.应用场景 ```javascript let p = new Promise((resolve, reject) => { setTimeout(() => { resolve('成功'); }, 3000); }) function wrap(p){ let abort; let p1 = new Promise((resolve,reject)=>{ abort = reject; }); let newPromise = Promise.race([p1,p]) newPromise.abort = abort return newPromise } let p1 = wrap(p); p1.then(data => { console.log('success', data) }, err => { console.log('error', err) }) setTimeout(() => { p1.abort('超过2s了'); }, 2000); ``` > 借助race的特点,可以实现立即中断promise变为失败态。常用作超时操作 #### 三.promisify原理 ```javascript function promisify(fn){ return function (...args) { return new Promise((resolve,reject)=>{ fn(...args,function (err,data) { if(err) reject(); resolve(data); }) }); } } let read = promisify(fs.readFile); ``` >我们可以快速的将node的api方法转化成promise,核心原理就是借助了error-first的特性。在内部手动处理错误 #### 四.generator使用 ###### 1.遍历器的基本实现 ```javascript const interable = { 0: 'a', 1: 'b', 2: 'c', length: 3 }; interable[Symbol.iterator] = function() { let index = 0; return { // 遍历器对象 next: () => { return { value: this[index], done: index++ == this.length } } } } ``` >如果我们自己去迭代一个对象需要实现一个迭代器接口,自己返回一个具有next方法的对象。内部会调用这个next方法返回结果包含value和done,当done为true时迭代完成。 ##### 2.通过生成器实现 ```javascript const iterable = { 0: 'a', 1: 'b', 2: 'c', length: 3 }; iterable[Symbol.iterator] = function*() { let index = 0; while (index !== this.length) { yield this[index++] } } console.log([...iterable]); ``` ##### 生成器使用 ```javascript function * read(){ // 感觉写代码就是同步的写,但是执行还是异步嵌套的执行 let content = yield fs.readFile('./name.txt','utf8'); // 1 let age = yield fs.readFile(content,'utf8'); // 2 return age; } ``` #### 五.co库原理 ```javascript function co(it){ return new Promise((resolve,reject)=>{ function next(data){ let {value,done} = it.next(data); if(!done){ Promise.resolve(value).then(data=>{ next(data); },reject) }else{ resolve(value); } } next(); }); } ``` > 这里我们主是掌握思想,异步迭代的思想。(产生一个迭代函数,当做回调函数使用) #### 六.浏览器事件环 ##### 1.浏览器的进程 - 每一个页卡都是进程 (互不影响) - 浏览器也有一个主进程 (用户界面) - 渲染进程 每个页卡里 都有一个渲染进程 (浏览器内核) - 网络进程 (处理请求) - GPU进程 3d绘制 - 第三方插件的进程 #### 2. 渲染进程(包含着多个线程) - GUI渲染线程 (渲染页面的) - js引擎线程 他和页面渲染时互斥 - 事件触发线程 独立的线程 EventLoop - 事件 click、setTimeout、ajax也是一个独立线程 事件环图[https://gitee.com/yuweiXia/study/blob/master/notes/%E6%B5%8F%E8%A7%88%E5%99%A8/eventLoop.jpg] #### 3.宏任务,微任务 - 宏任务 宿主环境提供的异步方法 都是宏任务 script ui 渲染 - 微任务 语言标准提供promise mutationObserver #### 任务执行面试题 ```javascript console.log(1); async function async () { console.log(2); await console.log(3); console.log(4) } setTimeout(() => { console.log(5); }, 0); const promise = new Promise((resolve, reject) => { console.log(6); resolve(7) }) promise.then(res => { console.log(res) }) async (); console.log(8); ``` >掌握Vue中nextTick原理