-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
158 changed files
with
6,506 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// 高阶函数是什么? 1. 一个函数的参数的参数是一个函数, 我们就可以称之为高阶函数 (回调函数) | ||
// 2. 一个函数返回一个函数 我们也称之为高阶函数 (不单指闭包) | ||
|
||
function coreFn(a,b,c){ | ||
// 实现了核心逻辑 | ||
console.log('core fn',a,b,c) | ||
} | ||
// 如果希望扩展公共的方法, 通过原型链扩展的属性是公共的 | ||
Function.prototype.before = function (beforeFn) { | ||
// this => coreFn | ||
return (...args)=>{ // newFn, 箭头函数的特点 没有this 没有arguments , 没有原型链 | ||
// 把所有的参数收集成一个数组 | ||
beforeFn(); | ||
this(...args); // 展开参数 | ||
} | ||
} | ||
let newFn = coreFn.before(()=>{ | ||
console.log('before fn') | ||
}) | ||
// code runner | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
const fs = require('fs').promises | ||
// Promise.all = function(promises) { | ||
// return new Promise((resolve, reject) => { | ||
// // 将数组中的promise依次执行 | ||
// let result = []; | ||
// let index = 0; | ||
// function process(v,k){ // after 实现是一致的 | ||
// result[k] = v; | ||
// if(++index == promises.length){ // 解决多个异步并发问题 只能靠计数器 | ||
// resolve(result); | ||
// } | ||
// } | ||
// for (let i = 0; i < promises.length; i++) { | ||
// let p = promises[i]; | ||
// if (p && typeof p.then === 'function') { | ||
// p.then(data => { // 异步 | ||
// process(data,i); | ||
// }, reject); // 如果有一个promise失败了 那么就执行最后的失败逻辑 | ||
// }else{ | ||
// process(p,i);// 同步的 | ||
// } | ||
// } | ||
// }) | ||
// } | ||
// // Promise.all 表示全部成功才成功, 如果一个失败了 则失败 | ||
// Promise.all([fs.readFile('name.txt', 'utf8'), fs.readFile('age.txt', 'utf8'), 11]).then(data => { | ||
// console.log(data); | ||
// }).catch(err => { | ||
// console.log(err) | ||
// }) | ||
// Promise.settled | ||
|
||
// 无论成功和失败都会执行的方法 和 try/catch/finally 不一样 | ||
|
||
Promise.prototype.finally = function (cb) { | ||
return this.then((y)=>{ | ||
return Promise.resolve(cb()).then((d)=>y); | ||
},(r)=>{ | ||
// cb执行一旦报错 就直接跳过后续的then的逻辑,直接将错误向下传递 | ||
return Promise.resolve(cb()).then(()=> {throw r}) | ||
}) | ||
} | ||
Promise.reject('ok').finally(()=>{ // finally 如果返回的是一个promise那么会有等待效果 | ||
console.log('无论成功失败都执行') | ||
return new Promise((resolve,reject)=>{ | ||
setTimeout(() => { | ||
resolve('xxxxxxxxxxx'); // 如果是失败 会用这里的失败作为失败的原因 | ||
}, 1000); | ||
}); | ||
}).then((data)=>{ | ||
console.log('成功',data) | ||
}).catch(err=>{ | ||
console.log('失败',err) | ||
}); | ||
|
||
|
||
// 事件环 同步异步,async await generator... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// 函数的柯里化 -》 高阶函数 | ||
|
||
// 柯里化的概念: 如果一个函数有多个参数, 我们可以根据参数的个数 转化成n个函数, 柯里化我们一般都认为参数是一个一个的传递的 | ||
// 偏函数: 根据参数的个数 分解成函数,每次调用函数的参数个数可以不是一个 | ||
|
||
// (如果我们想暂存参数 可以考虑使用柯里化 , 柯里化 就算是一个闭包函数) (更加具体的函数) | ||
|
||
// typeof > Array.isArray > Object.prototype.toString.call > instanceof > constructor | ||
|
||
function isType(type,val){ | ||
return Object.prototype.toString.call(val) === `[object ${type}]` | ||
} | ||
// function isType(type){ | ||
// return function (val){ | ||
// return Object.prototype.toString.call(val) === `[object ${type}]` | ||
// } | ||
// } | ||
let isString =curring(isType)('String'); | ||
let isNumber = curring(isType)('Number') | ||
let isBoolean = curring(isType)('Boolean'); | ||
|
||
|
||
console.log(isString(123)); | ||
console.log(isNumber(456)); | ||
console.log(isBoolean(123)); | ||
|
||
// -------------------------------- | ||
|
||
// 实现一个通用的柯里化函数 开发是经常使用的,面试中经常被问到 | ||
|
||
function sum(a,b,c,d){ | ||
return a+b+c+d; | ||
} | ||
// sum(1,2,3,4) | ||
|
||
function curring(fn){ | ||
let args = []; // 这里用来记录参数的个数, 记录每次调用传入的总个数 | ||
const inner = (arr = []) =>{ // 每次调用的个数 | ||
args.push(...arr); | ||
return args.length >= fn.length? fn(...args) : (...args)=> inner(args) // [2,3] | ||
} | ||
return inner(); | ||
} | ||
let fn = curring(sum) | ||
let fn1 = fn(1) | ||
let fn2 = fn1(2,3) | ||
let result = fn2(4); | ||
console.log(result); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
const fs = require('fs'); // 引入node中的fs模块 | ||
|
||
// 异步就是不能立即拿到返回值 , 通过回调的方式获取放回结果 | ||
|
||
// let school = {} | ||
// function finish() { | ||
// if (Reflect.ownKeys(school).length == 2) { // Object.keys() | ||
// console.log(school); // 渲染页面 | ||
// } | ||
// } | ||
function after(times, callback) { | ||
let data = {} | ||
return function finish(key, value) { // 函数声明所在的作用域 和执行的作用域不是同一个此时就会产生闭包 | ||
data[key] = value; | ||
if (Reflect.ownKeys(data).length == times) { | ||
callback(data); | ||
} | ||
} | ||
} | ||
let finish = after(2, (school) => { // 发布订阅模式 前端最常用的方式 | ||
console.log(school); | ||
}) | ||
fs.readFile('./name.txt', 'utf8', function(err, data) { | ||
// school['name'] = data; | ||
// finish(); | ||
finish('name', data) | ||
}) | ||
fs.readFile('./age.txt', 'utf8', function(err, data) { | ||
// school['age'] = data; | ||
// finish(); | ||
finish('age', data) | ||
}); | ||
|
||
|
||
|
||
// 对于前端 我们希望调用两个ajax 拿到最终的处理结果 去渲染页面 Promise.all | ||
|
||
// 1.不用promise 异步就用回调的方式 2.发布订阅模式 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
const fs = require('fs'); | ||
// function after(times, callback) { | ||
// let data = {} | ||
// return function finish(key, value) { | ||
// data[key] = value; | ||
// if (Reflect.ownKeys(data).length == times) { | ||
// callback(data); | ||
// } | ||
// } | ||
// } | ||
// let finish = after(2, (school) => { | ||
// console.log(school); | ||
// }) | ||
|
||
// 发布订阅模式 需要两个 方法 “订阅” “发布” 观察者模式 (观察者模式是基于发布订阅的, 观察者模式是基于类来实现的) | ||
|
||
// vue2 响应式原理 发布订阅还是观察者? 视图会依赖数据,数据变化后会“通知”视图更新 | ||
let event = { | ||
_arr:[], | ||
data:{}, | ||
on(fn){ | ||
this._arr.push(fn); | ||
}, | ||
emit(key,value){ | ||
this.data[key] = value; | ||
this._arr.forEach(fn=>fn(this.data)) | ||
} | ||
} | ||
event.on((data)=>{ // 订阅第一次 | ||
console.log('收到了一个数据',data) | ||
}) | ||
event.on((data)=>{ // 订阅第二次 | ||
if(Reflect.ownKeys(data).length == 2){ | ||
console.log('收到了全部数据',data) | ||
} | ||
}) | ||
fs.readFile('./name.txt', 'utf8', function(err, data) { | ||
event.emit('name', data) | ||
}) | ||
fs.readFile('./age.txt', 'utf8', function(err, data) { | ||
event.emit('age', data) | ||
}); | ||
|
||
// 发布订阅模式是基于一个中间 调度栈,发布和 订阅是解耦的 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// 观察者模式 需要有两个类 2. 观察者 | ||
class Subject{ // 1.被观察者 | ||
constructor(name){ | ||
this.name = name; | ||
this.observers = []; | ||
this.state = '开心' | ||
} | ||
attach(o){ | ||
this.observers.push(o); // 订阅模式, 被观察者需要接受观察者 | ||
} | ||
setState(newState){ | ||
this.state = newState | ||
this.observers.forEach(o=>o.update(newState)) | ||
} | ||
} | ||
class Observer{ // 2. 观察者 | ||
constructor(name){ | ||
this.name = name; | ||
} | ||
update(state){ | ||
console.log(this.name + ':' + '当前状态是' + state); | ||
} | ||
} | ||
// 我家有个小宝宝 , 爸爸和妈妈要关心小宝包的状态 , 小宝宝不开心 会主动通知观察者 | ||
let s = new Subject('宝宝'); | ||
let o1 = new Observer('爸爸'); | ||
let o2 = new Observer('妈妈'); | ||
s.attach(o1) | ||
s.attach(o2) | ||
s.setState('不开心'); | ||
s.setState('开心'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Promise 基本上不用关心浏览器的兼容性 | ||
// 正式课学员 最好能自己手写promise | ||
|
||
|
||
// Promise是一个类 我们可以new Promise 创造一个实例 | ||
// promise 有三个状态 1.默认状态叫等待态 pending 2.resolve表示成功态 fulfilled 3.reject表示变成失败态 rejected | ||
|
||
// 只有在pending的状态的时候才能改变状态, 不能从成功变成失败 , 不能从失败变成成功 | ||
|
||
// 成功有成功的原因 失败同样也有失败的原因 , 除了调用resolve和reject能改变状态外,还可以使用throwerror 抛出异常也会执行到失败的逻辑 | ||
|
||
let Promise = require('./promise'); | ||
let promise = new Promise((resolve, reject) => { | ||
setTimeout(() => { | ||
// throw new Error('error') | ||
reject('ok'); // 让promise变成成功态 | ||
resolve('ok') | ||
// return new Error('失败') | ||
}, 1000); | ||
}) | ||
|
||
promise.then((value) => { // then方法中提供两个参数 1. 成功回调 2.失败的回调 | ||
console.log(value, 'success') | ||
}, (reason) => { | ||
console.log(reason, 'fail') | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// let promise = new Promise((resolve,reject)=>{ | ||
// resolve('ok') | ||
// }); | ||
|
||
// promise.then((data)=>{ | ||
// console.log(data) | ||
// },()=>{ | ||
|
||
// }) | ||
let Promise = require('./promise') | ||
const fs = require('fs'); | ||
// 为什么要处理链式调用 我们写一个功能 先读取a.txt 文件,拿到具体的内容 读取内容对应的文件 | ||
// fs.readFile('./a.txt','utf8',function (err,data) { 回调地狱 错误不好处理,代码全部耦合在一起 | ||
// fs.readFile(data,'utf8',function (err,data) { | ||
// console.log(data); | ||
// }) | ||
// }) | ||
|
||
function readFile(...args){ | ||
return new Promise((resolve,reject)=>{ | ||
fs.readFile(...args,function (err,data) { | ||
if(err) return reject(err); | ||
resolve(data); | ||
}) | ||
}) | ||
} | ||
// 可以在then方法(成功和失败)中 返回一个promise, promose会采用返回的promise的成功的值或失败原因, 传递到外层下一次then中 | ||
|
||
// 1. then方法中 成功的回调或者失败的回调返回的是一个promise,那么会采用返回的promise的状态,走外层下一次then中的成功或失败, 同时将promise处理后的结果向下传递 | ||
// 2.then方法中 成功的回调或者失败的回调返回的是一个普通值 (不是promise) 这里会将返回的结果传递到下一次then的成功中去 | ||
// 3.如果在then方法中 成功的回调或者失败的回调 执行时出错会走到外层下一个then中的失败中去 | ||
let promise2 = readFile('./a.txt','utf8').then(data=>{ // 成功 -》 失败 | ||
throw new Error('123') | ||
},err=>{ | ||
return 200; | ||
}) | ||
promise2.then((data)=>{ | ||
console.log(data); | ||
},err=>{ | ||
console.log('err',err) | ||
}) | ||
// promise 一旦成功不能失败 | ||
// 如果返回的是一个失败的promoise 、 报错了 。才会走下一个then的失败,否则全部走成功 | ||
// 如何实现链式调用? return new Promise() 每次都产生一个全新的promise,来保证状态可以正常的切换 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
let Promise1 = require('./promise') | ||
|
||
// let promise2 = new Promise1((resolve,reject)=>{ | ||
// resolve('ok') | ||
// }).then(data=>{ // 成功 -》 失败 | ||
// return new Promise1((resolve,reject)=>{ | ||
// setTimeout(() => { | ||
// resolve(new Promise1((resolve,reject)=>{ | ||
// setTimeout(() => { | ||
// resolve('ok') | ||
// }, 2000); | ||
// })); | ||
// }, 1000); | ||
// }) | ||
// }) | ||
// promise2.then((data)=>{ | ||
// console.log(data); | ||
// },err=>{ | ||
// console.log('err',err) | ||
// }) | ||
|
||
|
||
// 问题1 循环引用的问题 | ||
// let promise2 = new Promise((resolve,reject)=>{ | ||
// resolve('ok') | ||
// }).then(data=>{ // 成功 -》 失败 | ||
// return promise2;// prending resolve()/reject() | ||
// }) | ||
// promise2.then((data)=>{ | ||
// console.log(data); | ||
// },err=>{ | ||
// console.log('err',err) | ||
// }) | ||
|
||
// 问题2 x.then出错 别人的promise 不知道咋写的,想定义不可枚举的属性 会采用defineProperty,在去取值和设置值的时候做额外逻辑 会采用defineProperty | ||
// Object.defineProperty(x,'then',{ | ||
// get(){ | ||
// if(times ==2){ | ||
// throw new Error() | ||
// } | ||
// } | ||
// }) | ||
|
||
// 问题3 可选参数 | ||
let p = new Promise1((resolve,reject)=>{ | ||
reject('ok') | ||
}).then().then().then((data)=>{ | ||
console.log(data); | ||
},err=>{ | ||
console.log(err,'err') | ||
}) |
Oops, something went wrong.