js 手写代码 1

253 阅读9分钟

object

1.clone

function clone1(target){
    //类型判断  {}  []  null
    if(typeof target === 'object' && target !== null){
        //判断数据是否为数组
        if(Array.isArray(target)){
            return [...target];
        }else{
            return {...target};
        }
    }else{
        return target;
    }
}

function clone2(target){
    //判断
    if(typeof target === 'object' && target !== null){
        //创建一个容器
        const result = Array.isArray(target) ? [] : {};
        //遍历 target 数据
        for(let key in target) {
            //判断当前对象身上是否包含该属性
            if(target.hasOwnProperty(key)){
                //将属性设置到 result 结果数据中
                result[key] = target[key];
            }
        }
        return result;
    }else{
        return target;
    }
}

function deepClone1(target){
    //通过数据创建 JSON 格式的字符串
    let str = JSON.stringify(target);
    //将 JSON 字符串创建为 JS 数据
    let data = JSON.parse(str);
    return data;    
}

function deepClone2(target){
    //检测数据的类型
    if(typeof target === 'object' && target !== null ){
        //创建一个容器
        const result = Array.isArray(target) ? [] : {};
        //遍历对象
        for(let key in target){
            //检测该属性是否为对象本身的属性(不能拷贝原型对象的属性)
            if(target.hasOwnProperty(key)){
                //拷贝
                result[key] = deepClone2(target[key]);
            }
        }
        return result;
    }else{
        return target;
    }
}

function deepClone3(target, map=new Map()){
    //检测数据的类型
    if(typeof target === 'object' && target !== null ){
        //克隆数据之前, 进行判断, 数据之前是否克隆过
        let cache = map.get(target);
        if(cache){
            return cache;
        }
        //创建一个容器
        const result = Array.isArray(target) ? [] : {};
        //将新的结果存入到容器中
        map.set(target, result);
        //遍历对象
        for(let key in target){
            //检测该属性是否为对象本身的属性(不能拷贝原型对象的属性)
            if(target.hasOwnProperty(key)){
                //拷贝
                result[key] = deepClone3(target[key], map);
            }
        }
        return result;
    }else{
        return target;
    }
}

function deepClone4(target, map=new Map()){
    //检测数据的类型
    if(typeof target === 'object' && target !== null ){
        //克隆数据之前, 进行判断, 数据之前是否克隆过
        let cache = map.get(target);
        if(cache){
            return cache;
        }
        //判断目标数据的类型
        let isArray = Array.isArray(target);
        //创建一个容器
        const result = isArray ? [] : {};
        //将新的结果存入到容器中
        map.set(target, result);
        //如果目标数据为数组
        if(isArray){
            //forEach 遍历
            target.forEach((item, index) => {
                result[index] = deepClone4(item, map);
            });
        }else{
            //如果是对象, 获取所有的键名, 然后 forEach 遍历
            Object.keys(target).forEach(key => {
                result[key] = deepClone4(target[key], map);
            });
        }
        return result;
    }else{
        return target;
    }
}


2.mergeObject

function mergeObject(...objs){
    //声明一个空对象
    const result = {};
    //遍历所有的参数对象
    objs.forEach(obj => {
        //获取当前对象所有的属性
        Object.keys(obj).forEach(key => {
            //检测 result 中是否存在 key 属性
            if(result.hasOwnProperty(key)){
                result[key] = [].concat(result[key], obj[key]);
            }else{
                //如果没有 则直接写入
                result[key] = obj[key];
            }
        });
    });
    return result;
}

3.myInstanceOf

function myInstanceOf(obj, Fn) {
  //获取函数的显式原型
  let prototype = Fn.prototype
  //获取 obj 的隐式原型对象
  let proto = obj.__proto__
  //遍历原型链
  while (proto) {
    //检测原型对象是否相等
    if (prototype === proto) {
      return true
    }
    //如果不等于
    proto = proto.__proto__
  }
  return false
}

function myInstanceOf(obj, Fn) {
  let proto = Object.getPrototypeOf(obj)

  while (true) {
    if (proto === null) return false

    if (proto === Fn.prototype) return true

    proto = Object.getPrototypeOf(proto)
  }
}

4.newInstance

function newInstance(Fn, ...args){
    //1. 创建一个新对象
    const obj = {};
    //2. 修改函数内部 this 指向新对象并执行
    const result = Fn.call(obj, ...args);
    //修改新对象的原型对象
    obj.__proto__ = Fn.prototype;
    //3. 返回新对象
    return result instanceof Object ? result : obj;
}

function

1.apply

function apply(Fn, obj, args) {
  obj = obj || globalThis

  obj.temp = Fn

  let arr = []
  for (let i = 0; i < args.length; i++) {
    arr.push(args[i])
  }
  
  let res = obj.temp(...arr)
  delete obj.temp
  return res
}

2.bind

function bind(Fn, obj, ...args){
    //返回一个新的函数
    return function(...args2){
        //执行 call 函数
        return call(Fn, obj, ...args, ...args2);
    }
}

3.call

function call(Fn, obj, ...args){
    //判断
    if(obj === undefined || obj === null){
        obj = globalThis;// 全局对象
    }
    //为 obj 添加临时的方法
    obj.temp = Fn;
    //调用 temp 方法
    let result = obj.temp(...args);
    //删除 temp 方法
    delete obj.temp;
    //返回执行结果
    return result;
}

4.debounce

function debounce(callback, time){
    //定时器变量
    let timeId = null;
    //返回一个函数
    return function(e){
        //判断
        if(timeId !== null){
            //清空定时器
            clearTimeout(timeId);
        }
        //启动定时器
        timeId = setTimeout(() => {
            //执行回调
            callback.call(this, e);
            //重置定时器变量
            timeId = null;
        }, time);
    }
}

5.throttle

 function throttle(callback, wait){
    //定义开始时间
    let start = 0;
    //返回结果是一个函数
    return function(e){
        //获取当前的时间戳
        let now = Date.now();
        //判断
        if(now - start >= wait){
            //若满足条件, 则执行回调函数
            callback.call(this, e);
            //修改开始时间
            start = now;
        }
    }
}

array

1. chunk

function chunk(arr, size = 1) {
  //判断
  if (arr.length === 0) {
    return []
  }
  //声明两个变量
  let result = []
  let tmp = [] // [1,2,3]
  //遍历
  arr.forEach((item) => {
    //判断tmp元素长度是否为 0
    if (tmp.length === 0) {
      //将 tmp 压入到 result 中
      result.push(tmp)
      // [ [1,2,3], [4,5,6], [7] ]
    }
    //将元素压入到临时数组 tmp 中
    tmp.push(item)
    //判断
    if (tmp.length === size) {
      tmp = []
    }
  })
  return result
}

2.concat


function concat(arr, ...args){
    //声明一个空数组
    const result = [...arr];
    //遍历数组
    args.forEach(item => {
        //判断 item 是否为数组
        if(Array.isArray(item)){
            result.push(...item);
        }else{
            result.push(item);
        }
    });
    //返回 result
    return result;
}


3.declares


function map(arr, callback){
    //声明一个空的数组
    let result = [];
    //遍历数组
    for(let i=0;i<arr.length;i++){
        //执行回调
        result.push(callback(arr[i], i));
    }
    //返回结果
    return result;
}

function reduce(arr, callback, initValue){
    //声明变量
    let result = initValue;
    //执行回调
    for(let i=0;i<arr.length;i++){
        //执行回调
        result = callback(result, arr[i]);
    }
    //返回最终的结果
    return result;
}

function filter(arr, callback){
    //声明空数组
    let result = [];
    //遍历数组
    for(let i=0;i<arr.length;i++){
        //执行回调
        let res = callback(arr[i], i);
        //判断 如果为真则压入到 result 结果中
        if(res){
            result.push(arr[i]);
        }
    }
    //返回结果
    return result;
}

function find(arr, callback){
    //遍历数组
    for(let i=0;i<arr.length;i++){
        //执行回调
        let res = callback(arr[i], i);
        //判断
        if(res){
            //返回当前正在遍历的元素
            return arr[i];
        }
    }
    //如果没有遇到满足条件的 返回 undefined
    return undefined;
}

function findIndex(arr, callback){
    //遍历数组
    for(let i=0;i<arr.length;i++){
        //执行回调
        let res = callback(arr[i], i);
        //判断
        if(res){
            //返回当前正在遍历的元素
            return i;
        }
    }
    //如果没有遇到满足条件的 返回 undefined
    return -1;
}

 function every(arr, callback){
    //遍历数组
    for(let i=0;i<arr.length;i++){
        // 执行回调 如果回调执行返回结果为 false
        if(!callback(arr[i], i)){
            return false;
        }
    }
    //如果都满足条件则返回 true
    return true;
}

function some(arr, callback){
    //遍历数组
    for(let i=0;i<arr.length;i++){
        // 执行回调 如果回调执行返回结果为 false
        if(callback(arr[i], i)){
            return true;
        }
    }
    //如果都满足条件则返回 true
    return false;
}

4.difference

function difference(arr1, arr2=[]){
    //判断参数
    if(arr1.length === 0){
        return [];
    }
    if(arr2.length === 0){
        return arr1.slice();
    }
    const result = arr1.filter(item => !arr2.includes(item));
    return result;
}

5.drop

function drop(arr, size){
    //过滤原数组 产生新数组
    // return arr.filter((value, index) => {
    //     //
    //     return index >= size; 
    // });
    return arr.filter((value, index) => index>=size);
}

function dropRight(arr, size){
    // return arr.filter((value,index)=>{
    //     return index < arr.length - size;
    // });
    return arr.filter((value, index) => index < arr.length - size);

}

6.flatten

function flatten1(arr){
    //声明空数组
    let result = [];
    //遍历数组
    arr.forEach(item => {
        //判断
        if(Array.isArray(item)){
            result = result.concat(flatten1(item));
        }else{
            result = result.concat(item);
        }
    });
    //返回结果
    return result;
}

function flatten2(arr){
    //声明数组
    let result = [...arr];
    //循环判断
    while(result.some(item => Array.isArray(item))){
        // [1,2,[3,4,[5,6]],7]
        // result = [].concat(1,2,[3,4,[5,6]],7);// [1,2,3,4,[5,6],7]
        // result = [].concat(1,2,3,4,[5,6],7);// [1,2,3,4,5,6,7]
        result = [].concat(...result);//
    }
    //返回结果
    return result;
}

7.pull

function pull(arr, ...args){
    //声明空数组  保存删掉的元素
    const result = [];
    //遍历 arr
    for(let i=0;i<arr.length;i++){
        //判断当前元素是否存在于 args 数组中
        if(args.includes(arr[i])){
            //将当前元素的值存入到 result 中
            result.push(arr[i]);
            //删除当前的元素
            arr.splice(i, 1);
            //下标自减
            i--;
        }
    }
    //返回
    return result;
}

function pullAll(arr, values){
    return pull(arr, ...values);
}

8.slice

function slice(arr, begin, end){
    //若arr数组长度为 0 
    if(arr.length === 0){
        return [];
    }
    //判断 begin
    begin = begin || 0;
    if(begin >= arr.length){
        return [];
    }
    //判断 end 
    end = end || arr.length;
    if(end < begin){
        end = arr.length;
    }

    //声明一个空数组
    const result = [];

    //遍历对象
    for(let i=0;i<arr.length;i++){
        if(i >= begin && i < end){
            //将下标对应的元素压入数组
            result.push(arr[i]);
        }
    }

    return result;
}

9.unique

function unique1(arr){
    //声明一个空数组
    const result = [];
    //遍历原始数组
    arr.forEach(item => {
        //检测 result 数组中是否包含这个元素
        if(result.indexOf(item) === -1) {
            //若没有该元素 则插入到result中
            result.push(item);
        }
    });
    //返回
    return result;
}

function unique2(arr){
    //声明空数组
    const result = [];
    //声明空对象
    const obj = {};
    //遍历数组
    arr.forEach(item => {
        if(obj[item] === undefined){
            //将 item 作为下标存储在 obj 中
            obj[item] = true;
            result.push(item);
        }
    });
    //返回结果
    return result;
}

function unique3(arr){
    // //将数组转化为集合 Set
    // let set = new Set(arr);
    // //将 set 展开创建一个数组
    // let array = [...set];
    // return array;
    return [...new Set(arr)];
}

其它

1. array to tree \ tree to array

// 转换前:
    source = [
        {
          id: 1,
          pid: 0,
          name: 'body',
        },
        {
          id: 2,
          pid: 1,
          name: 'title',
        },
        {
          id: 3,
          pid: 2,
          name: 'div',
        },
      ]
// 转换为: 
      tree = [
        {
          id: 1,
          pid: 0,
          name: 'body',
          children: [
            {
              id: 2,
              pid: 1,
              name: 'title',
              children: [
                {
                  id: 3,
                  pid: 1,
                  name: 'div',
                },
              ],
            },
          ],
        },
      ]

代码实现:

//数组转树
function arrayToTree(data) {
  // 初始化结果数组,并判断输入数据的格式
  let result = []
  if(!Array.isArray(data)) {
    return result
  }
  // 使用map,将当前对象的id与当前对象对应存储起来
  let map = {};
  data.forEach(item => {
    map[item.id] = item;
  });
  // 
  data.forEach(item => {
    let parent = map[item.pid];
    if(parent) {
      (parent.children || (parent.children = [])).push(item);
    } else {
      result.push(item);
    }
  });
  return result;
}
//树转数组
function treeToList(data, res = []) {
  data.forEach((item) => {
    res.push(item)
    if (item.children) {
      treeToList(item.children, res)
      delete item.children
    }
  })
  return res
}


//树转数组
function treeToArray(obj) {
  const stack = [] // 声明栈,用来存储待处理元素
  const res = [] // 接收结果
  stack.push(obj) // 将初始元素压入栈
  while (stack.length) {
    // 栈不为空则循环执行
    const item = stack[0] // 取出栈顶元素
    res.push(item) // 元素本身压入结果数组
    stack.shift() // 将当前元素弹出栈
    // 逻辑处理,如果当前元素包含子元素,则将子元素压入栈
    if (item.children && item.children.length) {
      stack.push(...item.children)
    }
  }
  return res
}

2. 手写 Promise

//声明构造函数
function Promise(executor){
    //添加属性
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    //声明属性
    this.callbacks = [];
    //保存实例对象的 this 的值
    const self = this;// self _this that
    //resolve 函数
    function resolve(data){
        //判断状态
        if(self.PromiseState !== 'pending') return;
        //1. 修改对象的状态 (promiseState)
        self.PromiseState = 'fulfilled';// resolved
        //2. 设置对象结果值 (promiseResult)
        self.PromiseResult = data;
        //调用成功的回调函数
        setTimeout(() => {
            self.callbacks.forEach(item => {
                item.onResolved(data);
            });
        });
    }
    //reject 函数
    function reject(data){
        //判断状态
        if(self.PromiseState !== 'pending') return;
        //1. 修改对象的状态 (promiseState)
        self.PromiseState = 'rejected';// 
        //2. 设置对象结果值 (promiseResult)
        self.PromiseResult = data;
        //执行失败的回调
        setTimeout(() => {
            self.callbacks.forEach(item => {
                item.onRejected(data);
            });
        });
    }
    try{
        //同步调用『执行器函数』
        executor(resolve, reject);
    }catch(e){
        //修改 promise 对象状态为『失败』
        reject(e);
    }
}

//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
    const self = this;
    //判断回调函数参数
    if(typeof onRejected !== 'function'){
        onRejected = reason => {
            throw reason;
        }
    }
    if(typeof onResolved !== 'function'){
        onResolved = value => value;
        //value => { return value};
    }
    return new Promise((resolve, reject) => {
        //封装函数
        function callback(type){
            try{
                //获取回调函数的执行结果
                let result = type(self.PromiseResult);
                //判断
                if(result instanceof Promise){
                    //如果是 Promise 类型的对象
                    result.then(v => {
                        resolve(v);
                    }, r=>{
                        reject(r);
                    })
                }else{
                    //结果的对象状态为『成功』
                    resolve(result);
                }
            }catch(e){
                reject(e);
            }
        }
        //调用回调函数  PromiseState
        if(this.PromiseState === 'fulfilled'){
            setTimeout(() => {
                callback(onResolved);
            });
        }
        if(this.PromiseState === 'rejected'){
            setTimeout(() => {
                callback(onRejected);
            });
        }
        //判断 pending 状态
        if(this.PromiseState === 'pending'){
            //保存回调函数
            this.callbacks.push({
                onResolved: function(){
                    callback(onResolved);
                },
                onRejected: function(){
                    callback(onRejected);
                }
            });
        }
    })
}

//添加 catch 方法
Promise.prototype.catch = function(onRejected){
    return this.then(undefined, onRejected);
}

//添加 resolve 方法
Promise.resolve = function(value){
    //返回promise对象
    return new Promise((resolve, reject) => {
        if(value instanceof Promise){
            value.then(v=>{
                resolve(v);
            }, r=>{
                reject(r);
            })
        }else{
            //状态设置为成功
            resolve(value);
        }
    });
}

//添加 reject 方法
Promise.reject = function(reason){
    return new Promise((resolve, reject)=>{
        reject(reason);
    });
}

//添加 all 方法
Promise.all = function (promises) {
  //返回结果为promise对象
  return new Promise((resolve, reject) => {
    //声明变量
    let count = 0
    let arr = []
    //遍历
    for (let i = 0; i < promises.length; i++) {
      //
      promises[i].then(
        (v) => {
          //得知对象的状态是成功
          //每个promise对象 都成功
          count++
          //将当前promise对象成功的结果 存入到数组中
          arr[i] = v
          //判断
          if (count === promises.length) {
            //修改状态
            resolve(arr)
          }
        },
        (r) => {
          reject(r)
        }
      )
    }
  })
}


//添加 race 方法
Promise.race = function(promises){
    return new Promise((resolve, reject) => {
        for(let i=0;i<promises.length;i++){
            promises[i].then(v => {
                //修改返回对象的状态为 『成功』
                resolve(v);
            },r=>{
                //修改返回对象的状态为 『失败』
                reject(r);
            })
        }
    });
}


class Promise{
    //构造方法
    constructor(executor){
        //添加属性
        this.PromiseState = 'pending';
        this.PromiseResult = null;
        //声明属性
        this.callbacks = [];
        //保存实例对象的 this 的值
        const self = this;// self _this that
        //resolve 函数
        function resolve(data){
            //判断状态
            if(self.PromiseState !== 'pending') return;
            //1. 修改对象的状态 (promiseState)
            self.PromiseState = 'fulfilled';// resolved
            //2. 设置对象结果值 (promiseResult)
            self.PromiseResult = data;
            //调用成功的回调函数
            setTimeout(() => {
                self.callbacks.forEach(item => {
                    item.onResolved(data);
                });
            });
        }
        //reject 函数
        function reject(data){
            //判断状态
            if(self.PromiseState !== 'pending') return;
            //1. 修改对象的状态 (promiseState)
            self.PromiseState = 'rejected';// 
            //2. 设置对象结果值 (promiseResult)
            self.PromiseResult = data;
            //执行失败的回调
            setTimeout(() => {
                self.callbacks.forEach(item => {
                    item.onRejected(data);
                });
            });
        }
        
        try{
            //同步调用『执行器函数』
            executor(resolve, reject);
        }catch(e){
            //修改 promise 对象状态为『失败』
            reject(e);
        }
    }

    //then 方法封装
    then(onResolved,onRejected){
        const self = this;
        //判断回调函数参数
        if(typeof onRejected !== 'function'){
            onRejected = reason => {
                throw reason;
            }
        }
        if(typeof onResolved !== 'function'){
            onResolved = value => value;
            //value => { return value};
        }
        return new Promise((resolve, reject) => {

            //封装函数
            function callback(type){
                try{
                    //获取回调函数的执行结果
                    let result = type(self.PromiseResult);
                    //判断
                    if(result instanceof Promise){
                        //如果是 Promise 类型的对象
                        result.then(v => {
                            resolve(v);
                        }, r=>{
                            reject(r);
                        })
                    }else{
                        //结果的对象状态为『成功』
                        resolve(result);
                    }
                }catch(e){
                    reject(e);
                }
            }

            //调用回调函数  PromiseState
            if(this.PromiseState === 'fulfilled'){
                setTimeout(() => {
                    callback(onResolved);
                });
            }

            if(this.PromiseState === 'rejected'){
                setTimeout(() => {
                    callback(onRejected);
                });
            }

            //判断 pending 状态
            if(this.PromiseState === 'pending'){
                //保存回调函数
                this.callbacks.push({
                    onResolved: function(){
                        callback(onResolved);
                    },
                    onRejected: function(){
                        callback(onRejected);
                    }
                });
            }
            
        })
    }

    //catch 方法
    catch(onRejected){
        return this.then(undefined, onRejected);
    }

    //添加 resolve 方法
    static resolve(value){
        //返回promise对象
        return new Promise((resolve, reject) => {
            if(value instanceof Promise){
                value.then(v=>{
                    resolve(v);
                }, r=>{
                    reject(r);
                })
            }else{
                //状态设置为成功
                resolve(value);
            }
        });
    }

    //添加 reject 方法
    static reject(reason){
        return new Promise((resolve, reject)=>{
            reject(reason);
        });
    }

    //添加 all 方法
    static all(promises){
        //返回结果为promise对象
        return new Promise((resolve, reject) => {
            //声明变量
            let count = 0;
            let arr = [];
            //遍历
            for(let i=0;i<promises.length;i++){
                //
                promises[i].then(v => {
                    //得知对象的状态是成功
                    //每个promise对象 都成功
                    count++;
                    //将当前promise对象成功的结果 存入到数组中
                    arr[i] = v;
                    //判断
                    if(count === promises.length){
                        //修改状态
                        resolve(arr);
                    }
                }, r => {
                    reject(r);
                });
            }
        });
    }

    //添加 race 方法
    static race (promises){
        return new Promise((resolve, reject) => {
            for(let i=0;i<promises.length;i++){
                promises[i].then(v => {
                    //修改返回对象的状态为 『成功』
                    resolve(v);
                },r=>{
                    //修改返回对象的状态为 『失败』
                    reject(r);
                })
            }
        });
    }
}   

3.axios

function axios({ method, url, params, data }) {
  //方法转化大写
  method = method.toUpperCase()
  //返回值
  return new Promise((resolve, reject) => {
    //四步骤
    //1. 创建对象
    const xhr = new XMLHttpRequest()

    //2. 初始化
    //处理 params 对象 a=100&b=200
    let str = ""
    for (let k in params) {
      str += `${k}=${params[k]}&`
    }
    str = str.slice(0, -1)


    
    xhr.open(method, url + "?" + str)

    //3. 发送
    if (method === "POST" || method === "PUT" || method === "DELETE") {
      //Content-type mime类型设置
      xhr.setRequestHeader("Content-type", "application/json")
      //设置请求体
      xhr.send(JSON.stringify(data))
    } else {
      xhr.send()
    }  
    //设置响应结果的类型为 JSON
    xhr.responseType = "json"

    //4. 处理结果
    xhr.onreadystatechange = function () {
      //
      if (xhr.readyState === 4) {
        //判断响应状态码 2xx
        if (xhr.status >= 200 && xhr.status < 300) {
          //成功的状态
          resolve({
            status: xhr.status,
            message: xhr.statusText,
            body: xhr.response,
          })
        } else {
          reject(new Error("请求失败, 失败的状态码为" + xhr.status))
        }
      }
    }
  })
}

axios.get = function (url, options) {
  //发送 AJAX 请求 GET
  let config = Object.assign(options, { method: "GET", url: url })

  return axios(config)
}

axios.post = function (url, options) {
  //发送 AJAX 请求 GET
  let config = Object.assign(options, { method: "POST", url: url })

  return axios(config)
}

axios.put = function (url, options) {
  //发送 AJAX 请求 GET
  let config = Object.assign(options, { method: "PUT", url: url })

  return axios(config)
}

axios.delete = function (url, options) {
  //发送 AJAX 请求 GET
  let config = Object.assign(options, { method: "delete", url: url })

  return axios(config)
}

4.event-bind

function addEventListener(el, type, fn, selector){
    //判断 el 的类型
    if(typeof el === 'string'){
        el = document.querySelector(el);
    }
    //事件绑定
    //若没有传递子元素的选择器, 则给 el 元素绑定事件
    if(!selector){
        el.addEventListener(type, fn);
    }else{
        el.addEventListener(type, function(e){
            //获取点击的目标事件源
            const target = e.target;
            //判断选择器与目标元素是否相符合
            if(target.matches(selector)){
                //若符合  则调用回调
                fn.call(target, e);
            }
        });
    }
}

5.event-bus

const eventBus = {
    //保存类型与回调的容器
    callbacks: {}
};

//绑定事件
eventBus.on = function(type, callback){
    //判断
    if(this.callbacks[type]){
        //如果 callbacks 属性中存在该类型事件 
        this.callbacks[type].push(callback);
    }else{
        //如果 callbacks 属性中不存在该类型事件 
        this.callbacks[type] = [callback];
    }
}

//触发事件
eventBus.emit = function(type, data){
    //判断
    if(this.callbacks[type] && this.callbacks[type].length > 0){
        //遍历数组
        this.callbacks[type].forEach(callback => {
            //执行回调
            callback(data);
        });
    }
}

//事件的解绑
eventBus.off = function(eventName){
    //若传入了 eventName 事件类型
    if(eventName){
        //只是删除 eventName 对应的事件回调
        delete this.callbacks[eventName];
    }else{
        this.callbacks = {};
    }
}

6.pub-sub

const PubSub = {
  //订阅唯一id
  id: 1,
  //频道与回调保存容器
  callbacks: {
    // pay: {
    //     token_1: fn
    //     token_2: fn
    // },
    // cancel: {
    //     token_3:
    //     token_4
    // },
    // other: {
    //     token_10
    // }
  },
}

/**订阅频道 */
PubSub.subscribe = function (channel, callback) {
  //创建唯一的编号
  let token = "token_" + this.id++ //
  //pay  token_1
  //判断 callbacks 属性中是否存在 pay
  if (this.callbacks[channel]) {
    this.callbacks[channel][token] = callback
  } else {
    this.callbacks[channel] = {
      [token]: callback,
    }
  }
  //返回频道订阅的 id
  return token
}   

/* 发布消息 */
PubSub.publish = function (channel, data) {
  //获取当前频道中所有的回调
  if (this.callbacks[channel]) {
    //
    Object.values(this.callbacks[channel]).forEach((callback) => {
      //执行回调
      callback(data)
    })
  }
}

/**取消订阅 */
//   1). 没有传值, flag 为 undefined
//   2). 传入token字符串
//   3). msgName字符串
PubSub.unsubscribe = function (flag) {
  //如果flag为undeined 则清空所有订阅
  if (flag === undefined) {
    this.callbacks = {}
  } else if (typeof flag === "string") {
    //判断是否为 token_ 开头
    if (flag.indexOf("token_") === 0) {
      //如果是 标明是一个订阅id
      let callbackObj = Object.values(this.callbacks).find((obj) =>
        obj.hasOwnProperty(flag)
      )
      //判断
      if (callbackObj) {
        delete callbackObj[flag]
      }
    } else {
      //表明是一个频道的名称
      delete this.callbacks[flag]
    }
  }
}

7.string

function reverseString(str){
    //将字符串转为数组
    // let arr = str.split('');
    let arr = [...str];
    //翻转数组
    arr.reverse();
    //将数组拼接成字符串
    let s = arr.join('');
    return s;
}

function palindrome(str){
    return reverseString(str) === str;
}

function truncate(str, size){
    return str.slice(0, size) + '...';
}