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 把不平整的地方垫起来