引言
🦐🦐🦐
1. 实现一个 new 关键字
function _new(fn, ...args) {
const obj = Object.create(fn.prototype); // 用fn原型创建一个对象obj
const ret = fn.apply(obj, args); // 执行fn
if((typeof ret === 'object'|| typeof ret ==='function')&&ret!==null){
return ret;
}
return obj;
}
2. 多维数组展平
使用reduce实现:
const flatten = arr => arr.reduce((p,n)=>p.concat(Array.isArray(n)?flatten(n):n),[]);
使用flatMap实现:
const flatten = arr => arr.flatMap(item=>Array.isArray(item)?flatten(item):item)
使用flat实现:
const flatten = (arr) => arr.flat(Infinity);
使用迭代实现
// es5
function flatten(arr){
var result = [];
var stack = Array.prototype.slice.call(arr);
while(stack.length){
var item = stack.shift();
if(Array.isArray(item)){
Array.prototype.push.apply(stack,item);
}else{
result.push(item)
}
}
return result;
}
// es6
const flatten = arr =>{
let result = [];
let stack = [...arr];
while(stack.length){
if(Array.isArray(item)){
stack.push(...item);
}else{
result.push(item);
}
}
return result;
}
3. 防抖
描述:高频事件触发n秒内只执行一次,如果n秒内重复触发,则重新计算时间
/*
* @param fn 需要防抖的函数
* @param delay 时间间隔
* @param immediately 第一次是否立即执行
*/
function debounce(fn,delay=500,immediately=true){
let timer = null;
let isFirstTime = true;
return function(...args){
clearTimeout(timer); // 重复触发时清除定时器
if(isFirstTime&&immediately){
fn.apply(this,args);
isFirstTime = false;
}else{
timer=setTimeout(()=>{
fn.apply(this,args)
},delay)
}
}
}
4. 节流
描述:高频函数在指定时间内只执行一次,重复触发也只执行一次,稀释函数的执行频率
/*
* @param fn 需要节流的函数
* @param delay 时间间隔
* @param immediately 第一次是否立即执行
*/
function throttle(fn,delay=500,immediately=true){
let lock = false;
let isFirstTime = true;
return function(...args){
if(lock) return false; // 加锁
lock = true;
if(isFirstTime&&immediately){
fn.apply(this,args);
lock = false;
return isFirstTime = false;
}
setTimeout(()=>{
lock = false;
fn.apply(this,args)
},delay)
}
}
5. 深度克隆
深度克隆一个对象,只复制可枚举的属性,不包括不可枚举属性以及原型链
function getType(obj){
return Object.prototype.toString.call(obj).slice(8,-1);
}
function cloneDeep(obj){
let target = {};
if(getType(obj)==='Object'){
for(let key in obj){
let item = obj[key];
target[key]=cloneDeep(item);
}
return target;
}
if(getType(obj)==='Array'){
return obj.map(item => cloneDeep(item) )
}
return obj;
}
6. 柯里化
当参数达到指定个数的时候执行方法,运用了递归与闭包
// es6
const curry = fn =>{
const g = (...allArgs) =>allArgs.length>=fn.length?fn(...allArgs):(...args)=>g(...allArgs,...args);
return g;
}
// es5
var currying = function(fn) {
function c() {
var allArgs = Array.prototype.slice.call(arguments,0);//保存所有的参数
if (allArgs.length>=fn.length) { // 如果大于函数的参数长度则触发
return fn.apply(this, allArgs);
}
return function(){ // 继续柯里化
var args = Array.prototype.slice.call(arguments,0);
return c.apply(this,allArgs.concat(args)); // 参数合并
};
}
return c;
}
7. 简单的发布订阅
简单的实现发布订阅模式,不保证严谨性
class EventEmitter{
events={}
on(event,fn){
if(event&&typeof fn === 'function'){
this.events[event]||(this.events[event]=[]);
this.events[event].push(fn);
}else{
throw new Error('params error');
}
}
emit(event,...args){
if(this.events[event]){
this.events[event].forEach(fn=>fn(...args));
}else{
throw new Error(`There is not an event:${event} in EventEmitter,you should register it first`);
}
}
}
const Event = new EventEmitter();
Event.on('click',(a,b)=>{
console.log('you click',`${a}-${b}`);
})
Event.emit('click','1','2'); // you click 1-2
Event.emit('touch'); // Error
8. lambda演算之Y组合子
Y 组合子是 lambda 演算中的一个概念,是任意函数的不动点,在函数式编程中主要作用是 提供一种匿名函数的递归方式。
const Y = f =>(x=>f(v=>x(x)(x)))(x=>f(v=>x(x)(v)))
9. js模拟实现call函数
Function.prototype.$call = function(target,...args) {
if(target===null||target===void 0){
target = window;
}else{
target = Object(target);
}
let fn = Symbol('__fn__');
target[fn] = this;
const ret = target[fn](...args);
delete target[fn];
return ret;
}
10. 广度遍历bfs
function bfs (tree) {
var stack = [...tree];
var res = [];
while (stack.length) {
var node = stack.shift();
if(node.children){
stack.push(...node.children);
}
console.log(node);
res.push(node);
}
return res;
}
11. 深度遍历dfs
function dfs(tree){
const queue = [...tree];
const res = [];
while(queue.length){
const node = queue.shift();
if(node.children){
queue.unshift(...node.children);
}
console.log(node);
res.push(node);
}
return res;
}
12. 反柯里 uncurring
Function.prototype.uncurring = function(){
var self = this;
return function(){
var obj = Array.prototype.shift.call(arguments);
return self.apply(obj,arguments);
}
}
var push = Array.prototype.push.uncurring();
var obj={
0:'1',
1:'2',
2:'3',
length:3
}
push(obj,'4') // 输出
13. 高阶函数实现AOP
Function.prototype.before = function(fn){
var self = this;
return function(){
fn.apply(this,arguments);
return self.apply(this,arguments);
}
}
Function.prototype.after = function(fn){
var self = this;
return function(){
var ret = self.apply(this,arguments);
fn.apply(this,arguments);
return ret;
}
}
// example
function a(i){
alert(i)
}
var $a = a.before(function(i){
console.log(i)
alert(0)
}).after(function(){
alert(2)
})
$(1);
14. 函数式编程之-管道函数
- f(g(k(v))): 嵌套地狱
- 理想方法:fn(f,g,k)(v)
const pipe = (...fns) => (p) => fns.reduce((v,f) => f(v),p);
// ;
15. koa中间件原理
const delay = async () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, 2000);
});
}
// 中间间模拟
const fn1 = async (ctx, next) => {
console.log(1);
await next();
console.log(2);
}
const fn2 = async (ctx, next) => {
console.log(3);
await delay();
await next();
console.log(4);
}
const fn3 = async (ctx, next) => {
console.log(5);
}
const middlewares = [fn1, fn2, fn3];
// compose 实现洋葱模型
const compose = (middlewares, ctx) => {
const dispatch = (i) => {
let fn = middlewares[i];
if(!fn){ return Promise.resolve() }
return Promise.resolve(fn(ctx, () => {
return dispatch(i+1);
}));
}
return dispatch(0);
}
compose(middlewares, 1);
16. js继承
es5寄生组合:
function Super(){};// 父类
function Sub(){ // 子类
Super.call(this);
};
function inherit(sub,sup){
sub.prototype = Object.create(sup.prototype);// 继承原型
sub.prototype.constructor = sub; // 改变
Object.setPrototypeOf(sub,sup)
};
inherit(Sub,Super);
var sub = new Sub();
console.log(sub);
es6 class:
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y);
this.color = color;
}
}
17.FVN hash函数
function hashFunction(key) {
const str = String(key);
let hash = 2166136261; // FNV_offset_basis (32 bit)
for (let i = 0; i < str.length; i += 1) {
hash ^= str.codePointAt(i); // XOR
hash *= 16777619; // 32 bit FNV_prime
}
return (hash >>> 0)
}