eventHub

198 阅读2分钟

EventHub 发布订阅模式
实现 on off emit once
作用:模块之间的信息传递

// 实现文件
class EventHub {
  constructor() {}
  cache = [];
  on(eventName, fn) {
    this.cache[eventName] = this.cache[eventName] || [];
    this.cache[eventName].push(fn);
  }
  emit(eventName, data?) {
    if (!this.cache[eventName]) return;
    this.cache[eventName].forEach((fn) => fn(data));
  }
  off(eventName, fn) {
    if (!this.cache[eventName]) return;
    let index = indexOf(this.cache[eventName], fn);
    if (index === -1) return;
    this.cache[eventName].splice(index, 1);
  }
}

/**
 * 帮助函数 indexOf
 */
function indexOf(array, value) {
  let index = -1;
  for (let i = 0; i < array.length; i++) {
    if (array[i] === value) {
      index = i;
      break;
    }
  }
  return index;
}

export default EventHub;

// 测试文件
import EventHub from '../src/index';
let test1 = (message) => {
  const eventhub = new EventHub();
  console.assert(eventhub instanceof Object === true, 'eventHub是个对象');
  console.log(message);
};

let test2 = (message) => {
  const eventhub = new EventHub();
  let called = false;
  eventhub.on('xxx', function (data) {
    console.assert(data === '今天的事情');
    called = true;
  });
  eventhub.emit('xxx', '今天的事情');
  console.assert(called);
  console.log(message);
};

let test3 = (message) => {
  const eventhub = new EventHub();
  let called = false;
  const callbackFn = function () {
    called = true;
  };
  eventhub.on('yyy', callbackFn);
  eventhub.off('yyy', callbackFn);
  eventhub.emit('yyy');
  console.assert(called === false);
  console.log(message);
};

test1('eventhub 是个函数');
test2('eventhub emit on 成功');
test3('eventhub off成功');


深拷贝
简单理解
b是a的一份拷贝,b中没有对a中对象的引用

json序列化,返序列化



let obj = {
    a: 1,
    b: [1,2,3],
    c: {c1:4},
    d: function(){
        console.log('ddd')
    },
    e: undefined
}

obj.self = obj
let obj2 = JSON.parse(JSON.stringify(obj))
console.log(obj)
console.log(obj2)
// 不支持fn
// 不支持undefined
// 不支持循环引用

// 时间,正则,symbolf


递归


let cache = [];
function deepClone (source) {
  if (source instanceof Object) {
    let cacheDist = findCache(source)
    if (cacheDist) {
      return cacheDist
    } else {
      let dist;
      if (source instanceof Array) {
        dist = new Array();
      } else if (source instanceof Function) {
        dist = function () {
          return source.call(this, ...arguments)
        }
      } else {
        dist = new Object()
      }
      cache.push([source, dist])
      for (let key in source) {
        if (source.hasOwnProperty(key)) {
          // 属性or原型属性
          dist[key] = deepClone(source[key])
        }

      }
      return dist
    }

  }
  return source
}


function findCache (source) {
  for (let i = 0; i < cache.length; i++) {
    if (cache[i][0] == source) {
      return cache[i][1]
    }
  }
  return undefined
}
module.exports = deepClone;

test

const chai = require('chai')
const sinon = require('sinon')
const sinonChai = require('sinon-chai')
chai.use(sinonChai)

const assert = chai.assert

const deepClone = require('../src/index')
describe('deepClone', () => {
  it('是一个函数', () => {
    assert.isFunction(deepClone)
  })

  it('能够复制基本类型', () => {
    const n = 123
    const n2 = deepClone(n)
    assert(n === n2)
  })

  describe('对象', () => {
    it('能够复制对象', () => {
      const a = { name: '名字', child: { name: 'child名字' } }
      const a2 = deepClone(a)
      assert(a !== a2)
      assert(a.name === a2.name)
      assert(a.child !== a2.child)
      assert(a.child.name === a2.child.name)
    })
    it('能够复制数组的对象', () => {
      const a = [[11, 12,], [21, 22], [31, 32]]
      const a2 = deepClone(a)
      assert(a !== a2)
      assert(a[0] !== a2[0])
      assert(a[1] !== a2[1])
      assert(a[2] !== a2[2])
      assert.deepEqual(a, a2)
    })
    it('能够复制函数', () => {
      const a = function (x, y) {
        return x + y
      }
      a.xxx = { yyy: { zzz: 1 } }
      a2 = deepClone(a)
      assert(a !== a2)
      assert(a.xxx.yyy.zzz === a2.xxx.yyy.zzz)
      assert(a.xxx.yyy !== a2.xxx.yyy)
      assert(a.xxx !== a2.xxx)
      assert(a(1, 2) === a2(1, 2))
    })
    it('环可以', () => {
      const a = { name: '名字' }
      a.self = a;
      const a2 = deepClone(a)
      assert(a !== a2)
      assert(a.name === a2.name)
      assert(a.self !== a2.self)
    })

    xit('不会爆栈', () => {
      const a = { child: null }
      let b = a
      for (let i = 0; i < 20000; i++) {
        b.child = { child: null }
        b = b.child
      }
      const a2 = deepClone(a)
      assert(a !== a2)
      assert(a.child !== a2.child)
    })

  })
})

bind
polyfill 把不平整的地方垫起来