FE-Interview
FE-Interview copied to clipboard
请实现`$on,$emit`
扫描下方二维码,获取答案以及详细解析,同时可解锁800+道前端面试题。
function Events() {
this.eventHub = {}
}
Events.prototype.$on = function(eventName, fn) {
this.eventHub[eventName] = (this.eventHub[eventName] || []).concat(fn)
}
Events.prototype.$emit = function(eventName, args) {
if (this.eventHub[eventName]) {
this.eventHub[eventName].forEach((fn) => {
fn(args)
})
}
}
Events.prototype.$off = function(eventName, fn) {
if (this.eventHub[eventName]) {
if (!fn) {
this.eventHub[eventName] = []
} else {
this.eventHub[eventName] = this.eventHub[eventName].filter(fun => fun !== fn)
}
}
}
Events.prototype.$once = function(eventName, fn) {
const fun = (...args) => {
fn.apply(this, args)
this.$off(eventName, fn)
}
this.$on(eventName, fun)
}
function test(a) {
console.log(a)
}
var event = new Events()
event.$once('test', test)
event.$emit('test', 1)
class Event {
constructor(){
this.eventHub = {};
}
on(eventName, fn){
(this.eventHub[eventName] || (this.eventHub[eventName] = [])).push(fn);
}
off(eventName, fn){
if(fn) {
if(Array.isArray(this.eventHub[eventName])) this.eventHub[eventName] = this.eventHub[eventName].filter(func => func !== fn);
}else {
this.eventHub[eventName] = [];
}
}
emit(eventName, ...args) {
if(Array.isArray(this.eventHub[eventName])) {
this.eventHub[eventName].forEach(fn => {
typeof fn === 'function' && fn.apply(this, args);
});
}
}
once(eventName, fn) {
const onceWrap = (...args) => {
fn.apply(this, args);
this.off(event, fn);
}
this.on(eventName, onceWrap);
}
}
function test(a) {
console.log(a)
}
var event = new Event()
event.once('test', test)
event.emit('test', 1) // 1
class Event {
constructor(){
this.eventHub = {};
}
on(eventName, fn){
(this.eventHub[eventName] || (this.eventHub[eventName] = [])).push(fn);
}
off(eventName, fn){
if(fn) {
if(Array.isArray(this.eventHub[eventName])){
console.log(this.eventHub[eventName].filter(func => func !== fn))
this.eventHub[eventName] = this.eventHub[eventName].filter(func => {
return func !== fn
});
}
}else {
this.eventHub[eventName] = [];
}
}
emit(eventName, ...args) {
if(Array.isArray(this.eventHub[eventName])) {
this.eventHub[eventName].forEach(fn => {
typeof fn === 'function' && fn.apply(this, args);
});
}
}
once(eventName, fn) {
const onceWrap = (...args) => {
fn.apply(this, args);
this.off(eventName, onceWrap);
}
this.on(eventName, onceWrap);
}
}
function Events() { this.eventHub = {} } Events.prototype.$on = function(eventName, fn) { this.eventHub[eventName] = (this.eventHub[eventName] || []).concat(fn) } Events.prototype.$emit = function(eventName, args) { if (this.eventHub[eventName]) { this.eventHub[eventName].forEach((fn) => { fn(args) }) } } Events.prototype.$off = function(eventName, fn) { if (this.eventHub[eventName]) { if (!fn) { this.eventHub[eventName] = [] } else { this.eventHub[eventName] = this.eventHub[eventName].filter(fun => fun !== fn) } } } Events.prototype.$once = function(eventName, fn) { const fun = (...args) => { fn.apply(this, args) this.$off(eventName, fn) } this.$on(eventName, fun) } function test(a) { console.log(a) } var event = new Events() event.$once('test', test) event.$emit('test', 1)
once方法会有问题,应该在 this.off中传入 eventName 和 onceWrap
class EventEmitter {
callbacks = new Map();
on = (eventName, callback) => {
if (!this.callbacks.has(eventName)) {
return void this.callbacks.set(eventName, [callback]);
}
const currentEventCallbacks = this.callbacks.get(eventName);
currentEventCallbacks.forEach(cb => {
if (cb === callback) {
return new Error("Try dupucate resgite callback");
}
});
currentEventCallbacks.push(callback);
this.callbacks.set(eventName, currentEventCallbacks);
};
emit = (eventName, ...args) => {
if (!this.callbacks.has(eventName)) {
return;
}
const currentEventCallbacks = this.callbacks.get(eventName);
currentEventCallbacks.forEach(cb => {
cb(...args);
});
};
once = (eventName, callback) => {
const executer = (...args) => {
unsubscribe(eventName, executer);
callback(...args);
};
this.on(eventName, executer);
};
unsubscribe = (eventName, callback) => {
if (!this.callbacks.has(eventName)) {
return;
}
const currentEventCallbacks = this.callbacks.get(eventName);
const leftCallbacks = currentEventCallbacks.filter(cb => cb !== callback);
if (leftCallbacks.length === 0) {
return this.callbacks.delete(eventName);
}
this.callbacks.set(eventName, leftCallbacks);
};
}