美文网首页
2020-05-13 4kyu Advanced Events

2020-05-13 4kyu Advanced Events

作者: 苦庭 | 来源:发表于2020-05-13 23:20 被阅读0次

https://www.codewars.com/kata/52d4678038644497e900007c

This excercise is a more sophisticated version of Simple Events kata.

Your task is to implement an Event constructor function for creating event objects

var event = new Event();

which comply to the following:

  • an event object should have .subscribe() and .unsubscribe() methods to add and remove handlers

  • .subscribe() and .unsubscribe() should be able take an arbitrary number of arguments and tolerate invalid arguments (not functions, or for unsubscribe, functions which are not subscribed) by simply skipping them

  • multiple subscription of the same handler is allowed, and in this case unsubscription removes the last subscription of the same handler

  • an event object should have an .emit() method which must invoke all the handlers with the arguments provided

  • .emit() should use its own invocation context as handers' invocation context

  • the order of handlers invocation must match the order of subscription

  • handler functions can subscribe and unsubscribe handlers, but the changes should only apply to the next emit call - the handlers for an ongoing emit call should not be affected

    • subscribe, unsubscribe and emit are the only public properties that are allowed on event objects (apart from Object.prototype methods)

Check the test fixture for usage example

My answer (跟着最佳答案改的)

function Event() {
  var handlers = [];
  this.subscribe = function(...args) {
    args.forEach(function(f){
      if(f && typeof f === "function")
        handlers.push(f);
    });
  }
  this.unsubscribe = function(...args) {
    args.forEach(function(f) {
      if(f && typeof f === "function") {  
        var index = handlers.lastIndexOf(f);
        if(index!==-1)
          handlers.splice(index, 1);
      }
    });
  }
  
  this.emit = function() {
    var args = arguments, cp_handlers = handlers.slice();
    cp_handlers.forEach(o => o.call(this, ...args));
  }
}

Best answer

function Event() {
  var queue = [];
  this.subscribe = function () {
    for (var i = 0; i < arguments.length; i++) {
      if (typeof arguments[i] == "function") queue.push(arguments[i]);
    }
  };
  this.unsubscribe = function () {
    for (var i = 0; i < arguments.length; i++) {
      var index = queue.lastIndexOf(arguments[i]);
      if (index >= 0) queue.splice(index, 1);
    }
  };
  this.emit = function () {
    var emit = queue.slice();
    while (emit.length) emit.shift().apply(this, arguments);
  };
}

Recap

  • 理解slice()的无参数用法,相当于深度复制一整个数组(非指针引用)
  • 掌握数组的lastIndexOf()的用法
  • 和Simple Events不同的地方在于,本题不能出现除subscribe/unsubcribe/emit外的其他的公有属性,而使用prototype只要访问公有的,因此不能够用原型链

相关文章

网友评论

      本文标题:2020-05-13 4kyu Advanced Events

      本文链接:https://www.haomeiwen.com/subject/tauanhtx.html