- 洗牌算法
把一个数组里的元素随机打乱顺序(Fisher-Yates 洗牌算法)
const shuffle = (arr) => {
for (let i = arr.length - 1; i > 0; i--) {
const j = (Math.floor((i + 1) * Math.random())[
//math.random生成[0,1)区间随机数
(arr[j], arr[i])
] = [arr[i], arr[j]]);
}
return arr;
};
-
继承套餐
-
原型继承
function Person() { this.name = "Navi"; } Person.prototype.eating = function () { console.log("eating"); }; //相当于定义了一个person类 function Student() {} Student.prototype = new Person(); //prototype也是对象(用来挂方法),可以换成一个person实例 const stu = new Student(); console.log(stu.name); // "juege" stu.eating(); // "eating" -
借用构造函数继承
function Person(name) { this.name = name; this.hobbies = ["eat", "sleep"]; } function Students(name, number) { Person.call(this, name); // 此时 this 指向当前新创建的 Student 实例(s1,s2) // Person.call(this, name) // 相当于让Person里面的this指向当前 Student 实例 // 从而把Person中定义的属性添加到 Student 实例上 this.number = number; //students自己的this } const s1 = new Students("Tom", 1001); const s2 = new Students("Jerry", 1002); console.log(s1); console.log(s2); // { // name: 'Tom', // hobbies: ['eat', 'sleep'], // number: 1001 // } -
寄生组合式继承(把子类原型的 proto 接到父类原型上)
还不太会敲
function Person(name, age) { // 每个实例自己的属性 this.name = name; this.age = age; } // 父类原型上的共享方法 Person.prototype.running = function () { console.log("我会跑"); }; function Student(name, age, number) { // 1. 借用父构造函数 // 让 Person 里的 this 指向当前 Student 实例 // 所以 name、age 会直接添加到 Student 实例自己身上 Person.call(this, name, age); // Student 自己的属性 this.number = number; } inheritPrototype(Student, Person); function inheritPrototype(children, parent) { children.prototype = Object.create(parent.prototype); //@param o — Object to use as a prototype. //aka Student.prototype.__proto__ = Person.prototype //s1 自己找不到某个属性时,就去 Student.prototype 上找。 //上一句把 children.prototype 整个换成了一个新对象 // 原来 Student.prototype 里的 constructor: Student 就没了 // // 所以重新给新的 Student.prototype 加上constructor: Student Object.defineProperty(children.prototype, "constructor", { value: children, // constructor 指回 Student enumerable: false, // 不可枚举 configurable: true, // 可以再次修改 writable: true, // 可以重新赋值 }); }
-
-
Promise
Promise → resolve/reject → then/catch
.then() 的第一个回调(箭头函数)会在 Promise fulfilled 后执行;.then() 的第二个回调或 .catch() 会在 Promise rejected 后执行。
resolve(value)会让 Promise 进入 fulfilled 状态,value会传给.then()里面的第一个箭头函数。reject(error)会让 Promise 进入 rejected 状态,error会传给.then()的第二个箭头函数,没有的话就会传给.catch(),当然then只会返回一个promise.then() 或 .catch() 返回的新 Promise:回调正常 return 普通值 -> fulfilled; 回调 throw new Error(“出错!”) 或者return Promise.reject(…) -> rejected;
.then()里面如果自己报错,也会被后面的 catch 接住。
Promise.all()是JavaScript中的一个静态方法,它接受一个Promise实例的数组作为参数,(或者它接受一个可迭代对象作为参数,其中可以包含 Promise 或普通值)并返回一个新的 Promise。并返回一个新的Promise实例。这个新的Promise实例的状态将在所有传递的Promise实例都变为fulfilled,并且它的完成值将是一个包含所有传递Promise实例完成值的数组。
当所有传递的Promise实例都fulfilled,then()方法指定的回调函数将被调用,并且它的参数将是一个包含所有Promise实例完成值的数组(也就是前面说的)。如果其中任意一个Promise实例的状态变为已失败,则Promise.all()方法返回的Promise实例的状态也将变为已失败,并且将调用catch()方法指定的回调函数。
- 手写 Promise.all 基础版
function promiseAll(promises) { // promiseAll 自己也要返回一个 Promise // 这样外面才能继续 .then() / .catch() return new Promise((resolve, reject) => { // 用来保存每一个 Promise 成功后的结果 const res = [] // len 一开始表示 Promise 的数量 // 后面每成功一个就 len-- let len = promises.length // 如果传进来的是空数组 [] // 直接成功,结果就是 [] if (!len) resolve(res) // 某一个 Promise 成功之后调用这个函数 function fulfill(idx, val) { // 按原来的下标保存结果 // 不能用 push,因为 Promise 完成顺序不一定和传入顺序一样 res[idx] = val // 成功完成一个 len-- // len === 0 // 说明所有 Promise 都成功了 if (!len) { resolve(res) } } // 遍历每一个 Promise promises.forEach((promise, idx) => { // Promise.resolve(promise) // 如果 promise 本来就是 Promise,就直接使用 // 如果是普通值,比如 1,就包装成成功的 Promise Promise.resolve(promise) // 当前 Promise 成功 // val 就是它 resolve 出来的结果 .then((val) => fulfill(idx, val)) // 当前 Promise 失败 // 任意一个失败,整个 Promise.all 直接失败 .catch((e) => reject(e)) }) })
}
- 手写 Promise.all 加强版 ```js function promiseAll(iterable){ const promises = Array.from(iterable) //把可迭代对象转为数组(常见的可迭代对象有ArrayStringSet集合Map) return new Promise((resolve,reject)=>{ const result=[] let count=0 const len=promises.length if(len===0){ resolve(result) } promises.forEach((promise,index)=>{ Promise.resolve(promise).then( (value)=>{ result[index]=value count++ if(count===len)resolve(result) } ).catch(reject)//失败后再调用这个Promise的reject //等价于.catch((error)=>reject(error)) }) }) }- 手写 Promise.allSettled
- 不管成功失败都等完
- 最后返回每一个 Promise 的状态
Promise.allSettled = function (promises) { // allSettled 最终不会因为某个子 Promise 失败而 reject // 所以这里甚至只需要 resolve return new Promise((resolve) => { // map 会把每一个 Promise 转换成一个“永远会成功”的 Promise const results = promises.map((promise) => { return promise.then( // 当前 Promise 成功 (value) => { // 不直接返回 value // 而是包装成一个对象 return { status: "fulfilled", value: value } }, // 当前 Promise 失败 (reason) => { // .then() 或 .catch() 返回的新 Promise: // 回调正常 return 普通值 -> fulfilled // 回调 throw 错误 -> rejected // 回调 return Promise.reject(...) -> rejected return { status: "rejected", reason: reason } } ) }) // 此时 results 里面的每一个 Promise // 都会成功,不会失败 // // 所以就可以放心使用 Promise.all Promise.all(results).then((settledResults) => { // 全部结束以后,把所有结果返回 resolve(settledResults) }) }) - 手写 Promise.all 基础版
}