ter = array_value($config, 'filter'); $arr = array_value($filter, $type); $enable = array_value($arr, 'enable'); $wordarr = array_value($arr, 'keyword'); if (0 == $enable || empty($wordarr)) return FALSE; foreach ($wordarr as $_keyword) { if (!$_keyword) continue; $r = strpos(strtolower($keyword), strtolower($_keyword)); if (FALSE !== $r) { $error = $_keyword; return TRUE; } } return FALSE; } // return http://domain.com OR https://domain.com function url_prefix() { $http = ((isset($_SERVER['HTTPS']) && 'on' == $_SERVER['HTTPS']) || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https://' : 'http://'; return $http . $_SERVER['HTTP_HOST']; } // 唯一身份ID function uniq_id() { return uniqid(substr(md5(microtime(true) . mt_rand(1000, 9999)), 8, 8)); } // 生成订单号 14位 function trade_no() { $trade_no = str_replace('.', '', microtime(1)); $strlen = mb_strlen($trade_no, 'UTF-8'); $strlen = 14 - $strlen; $str = ''; if ($strlen) { for ($i = 0; $i <= $strlen; $i++) { if ($i < $strlen) $str .= '0'; } } return $trade_no . $str; } // 生成订单号 16位 function trade_no_16() { $explode = explode(' ', microtime()); $trade_no = $explode[1] . mb_substr($explode[0], 2, 6, 'UTF-8'); return $trade_no; } // 当前年的天数 function date_year($time = NULL) { $time = intval($time) ? $time : time(); return date('L', $time) + 365; } // 当前年份中的第几天 function date_z($time = NULL) { $time = intval($time) ? $time : time(); return date('z', $time); } // 当前月份中的第几天,没有前导零 1 到 31 function date_j($time = NULL) { $time = intval($time) ? $time : time(); return date('j', $time); } // 当前月份中的第几天,有前导零的2位数字 01 到 31 function date_d($time = NULL) { $time = intval($time) ? $time : time(); return date('d', $time); } // 当前时间为星期中的第几天 数字表示 1表示星期一 到 7表示星期天 function date_w_n($time = NULL) { $time = intval($time) ? $time : time(); return date('N', $time); } // 当前日第几周 function date_d_w($time = NULL) { $time = intval($time) ? $time : time(); return date('W', $time); } // 当前几月 没有前导零1-12 function date_n($time = NULL) { $time = intval($time) ? $time : time(); return date('n', $time); } // 当前月的天数 function date_t($time = NULL) { $time = intval($time) ? $time : time(); return date('t', $time); } // 0 o'clock on the day function clock_zero() { return strtotime(date('Ymd')); } // 24 o'clock on the day function clock_twenty_four() { return strtotime(date('Ymd')) + 86400; } // 8点过期 / expired at 8 a.m. function eight_expired($time = NULL) { $time = intval($time) ? $time : time(); // 当前时间大于8点则改为第二天8点过期 $life = date('G') <= 8 ? (strtotime(date('Ymd')) + 28800 - $time) : clock_twenty_four() - $time + 28800; return $life; } // 24点过期 / expired at 24 a.m. function twenty_four_expired($time = NULL) { $time = intval($time) ? $time : time(); $twenty_four = clock_twenty_four(); $life = $twenty_four - $time; return $life; } /** * @param $url 提交地址 * @param string $post POST数组 / 空为GET获取数据 / $post='GET'获取连续跳转最终URL * @param string $cookie cookie * @param int $timeout 超时 * @param int $ms 设为1是毫秒 * @return mixed 返回数据 */ function https_request($url, $post = '', $cookie = '', $timeout = 30, $ms = 0) { if (empty($url)) return FALSE; if (version_compare(PHP_VERSION, '5.2.3', '<')) { $ms = 0; $timeout = 30; } is_array($post) and $post = http_build_query($post); // 没有安装curl 使用http的形式,支持post if (!extension_loaded('curl')) { //throw new Exception('server not install CURL'); if ($post) { return https_post($url, $post, $cookie, $timeout); } else { return http_get($url, $cookie, $timeout); } } is_array($cookie) and $cookie = http_build_query($cookie); $curl = curl_init(); // 返回执行结果,不输出 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); //php5.5跟php5.6中的CURLOPT_SAFE_UPLOAD的默认值不同 if (class_exists('\CURLFile')) { curl_setopt($curl, CURLOPT_SAFE_UPLOAD, true); } else { defined('CURLOPT_SAFE_UPLOAD') and curl_setopt($curl, CURLOPT_SAFE_UPLOAD, false); } // 设定请求的RUL curl_setopt($curl, CURLOPT_URL, $url); // 设定返回信息中包含响应信息头 if (ini_get('safe_mode') && ini_get('open_basedir')) { // $post参数必须为GET if ('GET' == $post) { // 安全模式时将头文件的信息作为数据流输出 curl_setopt($curl, CURLOPT_HEADER, true); // 安全模式采用连续抓取 curl_setopt($curl, CURLOPT_NOBODY, true); } } else { curl_setopt($curl, CURLOPT_HEADER, false); // 允许跳转10次 curl_setopt($curl, CURLOPT_MAXREDIRS, 10); // 使用自动跳转,返回最后的Location curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); } $ua1 = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1'; $ua = empty($_SERVER["HTTP_USER_AGENT"]) ? $ua1 : $_SERVER["HTTP_USER_AGENT"]; curl_setopt($curl, CURLOPT_USERAGENT, $ua); // 兼容HTTPS if (FALSE !== stripos($url, 'https://')) { curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); //ssl版本控制 //curl_setopt($curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); curl_setopt($curl, CURLOPT_SSLVERSION, true); } $header = array('Content-type: application/x-www-form-urlencoded;charset=UTF-8', 'X-Requested-With: XMLHttpRequest'); $cookie and $header[] = "Cookie: $cookie"; curl_setopt($curl, CURLOPT_HTTPHEADER, $header); if ($post) { // POST curl_setopt($curl, CURLOPT_POST, true); // 自动设置Referer curl_setopt($curl, CURLOPT_AUTOREFERER, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $post); } if ($ms) { curl_setopt($curl, CURLOPT_NOSIGNAL, true); // 设置毫秒超时 curl_setopt($curl, CURLOPT_TIMEOUT_MS, intval($timeout)); // 超时毫秒 } else { curl_setopt($curl, CURLOPT_TIMEOUT, intval($timeout)); // 秒超时 } //优先解析 IPv6 超时后IPv4 //curl_setopt($curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); curl_setopt($curl, CURLOPT_ENCODING, 'gzip'); // 返回执行结果 $output = curl_exec($curl); // 有效URL,输出URL非URL页面内容 CURLOPT_RETURNTRANSFER 必须为false 'GET' == $post and $output = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL); curl_close($curl); return $output; } function save_image($img) { $ch = curl_init(); // 设定请求的RUL curl_setopt($ch, CURLOPT_URL, $img); // 设定返回信息中包含响应信息头 启用时会将头文件的信息作为数据流输出 //curl_setopt($ch, CURLOPT_HEADER, false); //curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER["HTTP_USER_AGENT"]); // true表示$html,false表示echo $html curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); //curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0); curl_setopt($ch, CURLOPT_ENCODING, 'gzip'); $output = curl_exec($ch); curl_close($ch); return $output; } // 计算字串宽度:剧中对齐(字体大小/字串内容/字体链接/背景宽度/倍数) function calculate_str_width($size, $str, $font, $width, $multiple = 2) { $box = imagettfbbox($size, 0, $font, $str); return ($width - $box[4] - $box[6]) / $multiple; } // 搜索目录下的文件 比对文件后缀 function search_directory($path) { if (is_dir($path)) { $paths = scandir($path); foreach ($paths as $val) { $sub_path = $path . '/' . $val; if ('.' == $val || '..' == $val) { continue; } else if (is_dir($sub_path)) { //echo '目录名:' . $val . '
'; search_directory($sub_path); } else { //echo ' 最底层文件: ' . $path . '/' . $val . '
'; $ext = strtolower(file_ext($sub_path)); if (in_array($ext, array('php', 'asp', 'jsp', 'cgi', 'exe', 'dll'), TRUE)) { echo '异常文件:' . $sub_path . '
'; } } } } } // 一维数组转字符串 $sign待签名字符串 $url为urlencode转码GET参数字符串 function array_to_string($arr, &$sign = '', &$url = '') { if (count($arr) != count($arr, 1)) throw new Exception('Does not support multi-dimensional array to string'); // 注销签名 unset($arr['sign']); // 排序 ksort($arr); reset($arr); // 转字符串做签名 $url = ''; $sign = ''; foreach ($arr as $key => $val) { if (empty($val) || is_array($val)) continue; $url .= $key . '=' . urlencode($val) . '&'; $sign .= $key . '=' . $val . '&'; } $url = substr($url, 0, -1); $url = htmlspecialchars($url); $sign = substr($sign, 0, -1); } // 私钥生成签名 function rsa_create_sign($data, $key, $sign_type = 'RSA') { if (!function_exists('openssl_sign')) throw new Exception('OpenSSL extension is not enabled'); if (!defined('OPENSSL_ALGO_SHA256')) throw new Exception('Only versions above PHP 5.4.8 support SHA256'); $key = wordwrap($key, 64, "\n", true); if (FALSE === $key) throw new Exception('Private Key Error'); $key = "-----BEGIN RSA PRIVATE KEY-----\n$key\n-----END RSA PRIVATE KEY-----"; if ('RSA2' == $sign_type) { openssl_sign($data, $sign, $key, OPENSSL_ALGO_SHA256); } else { openssl_sign($data, $sign, $key, OPENSSL_ALGO_SHA1); } // 加密 return base64_encode($sign); } // 公钥验证签名 function rsa_verify_sign($data, $sign, $key, $sign_type = 'RSA') { $key = wordwrap($key, 64, "\n", true); if (FALSE === $key) throw new Exception('Public Key Error'); $key = "-----BEGIN PUBLIC KEY-----\n$key\n-----END PUBLIC KEY-----"; // 签名正确返回1 签名不正确返回0 错误-1 if ('RSA2' == $sign_type) { $result = openssl_verify($data, base64_decode($sign), $key, OPENSSL_ALGO_SHA256); } else { $result = openssl_verify($data, base64_decode($sign), $key, OPENSSL_ALGO_SHA1); } return $result === 1; } // Array to xml array('appid' => 'appid', 'code' => 'success') function array_to_xml($arr) { if (!is_array($arr) || empty($arr)) throw new Exception('Array Error'); $xml = ""; foreach ($arr as $key => $val) { if (is_numeric($val)) { $xml .= "<" . $key . ">" . $val . ""; } else { $xml .= "<" . $key . ">"; } } $xml .= ""; return $xml; } // Xml to array function xml_to_array($xml) { if (!$xml) throw new Exception('XML error'); $old = libxml_disable_entity_loader(true); // xml解析 $result = (array)simplexml_load_string($xml, null, LIBXML_NOCDATA | LIBXML_COMPACT); // 恢复旧值 if (FALSE === $old) libxml_disable_entity_loader(false); return $result; } // 逐行读取 function well_import($file) { if ($handle = fopen($file, 'r')) { while (!feof($handle)) { yield trim(fgets($handle)); } fclose($handle); } } // 计算总行数 function well_import_total($file, $key = 'well_import_total') { static $cache = array(); if (isset($cache[$key])) return $cache[$key]; $count = cache_get($key); if (NULL === $count) { $count = 0; $globs = well_import($file); while ($globs->valid()) { ++$count; $globs->next(); // 指向下一个 } $count and cache_set($key, $count, 300); } return $cache[$key] = $count; } $g_dir_file = FALSE; function well_search_dir($path) { global $g_dir_file; FALSE === $g_dir_file and $g_dir_file = array(); if (is_dir($path)) { $paths = scandir($path); foreach ($paths as $val) { $sub_path = $path . '/' . $val; if ('.' == $val || '..' == $val) { continue; } else if (is_dir($sub_path)) { well_search_dir($sub_path); } else { $g_dir_file[] = $sub_path; } } } return $g_dir_file; } ?>Douglas Crockford&#39;s &quot;Javascript: The Good Parts&quot; Chapter 5.5 - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Douglas Crockford&#39;s &quot;Javascript: The Good Parts&quot; Chapter 5.5 - Stack Overflow

programmeradmin2浏览0评论

I was reading Ch 5.5 of the book in title. I have still have trouble in seeing how "We can pose objects out of sets of parts" using the eventuality function in the chapter.

Are objects to be posed by a event system with the "on" and "fire" functions ?

Code from the section of the book below:

var eventuality = function (that) {
    var registry = {};
    that.fire = function (event) {
// Fire an event on an object. The event can be either
// a string containing the name of the event or an
// object containing a type property containing the
// name of the event. Handlers registered by the 'on'
// method that match the event name will be invoked.
        var array,
            func,
            handler,
            i,
            type = typeof event === 'string' ?
                    event : event.type;
// If an array of handlers exist for this event, then
// loop through it and execute the handlers in order.
        if (registry.hasOwnProperty(type)) {
            array = registry[type];
            for (i = 0; i < array.length; i += 1) {
                handler = array[i];
// A handler record contains a method and an optional
// array of parameters. If the method is a name, look
// up the function.
                func = handler.method;
                if (typeof func === 'string') {
                    func = this[func];
                }
// Invoke a handler. If the record contained
// parameters, then pass them. Otherwise, pass the
// event object.
                func.apply(this,
                    handler.parameters || [event]);
            }
        }
        return this;
    };
    that.on = function (type, method, parameters) {
// Register an event. Make a handler record. Put it
// in a handler array, making one if it doesn't yet
// exist for this type.
        var handler = {
            method: method,
            parameters: parameters
        };
        if (registry.hasOwnProperty(type)) {
            registry[type].push(handler);
        } else {
            registry[type] = [handler];
        }
        return this;
    };
    return that;
}

I was reading Ch 5.5 of the book in title. I have still have trouble in seeing how "We can pose objects out of sets of parts" using the eventuality function in the chapter.

Are objects to be posed by a event system with the "on" and "fire" functions ?

Code from the section of the book below:

var eventuality = function (that) {
    var registry = {};
    that.fire = function (event) {
// Fire an event on an object. The event can be either
// a string containing the name of the event or an
// object containing a type property containing the
// name of the event. Handlers registered by the 'on'
// method that match the event name will be invoked.
        var array,
            func,
            handler,
            i,
            type = typeof event === 'string' ?
                    event : event.type;
// If an array of handlers exist for this event, then
// loop through it and execute the handlers in order.
        if (registry.hasOwnProperty(type)) {
            array = registry[type];
            for (i = 0; i < array.length; i += 1) {
                handler = array[i];
// A handler record contains a method and an optional
// array of parameters. If the method is a name, look
// up the function.
                func = handler.method;
                if (typeof func === 'string') {
                    func = this[func];
                }
// Invoke a handler. If the record contained
// parameters, then pass them. Otherwise, pass the
// event object.
                func.apply(this,
                    handler.parameters || [event]);
            }
        }
        return this;
    };
    that.on = function (type, method, parameters) {
// Register an event. Make a handler record. Put it
// in a handler array, making one if it doesn't yet
// exist for this type.
        var handler = {
            method: method,
            parameters: parameters
        };
        if (registry.hasOwnProperty(type)) {
            registry[type].push(handler);
        } else {
            registry[type] = [handler];
        }
        return this;
    };
    return that;
}
Share Improve this question edited May 30, 2011 at 8:33 isNaN1247 18.1k13 gold badges74 silver badges119 bronze badges asked May 30, 2011 at 8:09 user670800user670800 1,1151 gold badge11 silver badges16 bronze badges 4
  • 3 It would be nice of you could also post some code so that people can help you who don't have the book ;) – Felix Kling Commented May 30, 2011 at 8:11
  • 3 The free chapter can be found @ yuiblog./assets/pdf/crockford-good-parts-ch-5.pdf – KooiInc Commented May 30, 2011 at 8:17
  • 2 For those with the book its page 55 - heading is 'Parts' – isNaN1247 Commented May 30, 2011 at 8:20
  • 1 What exactly is your question again? The methods fire and on are added to the object at run time (dynamically). I think that is the whole point. – Felix Kling Commented May 30, 2011 at 8:35
Add a ment  | 

5 Answers 5

Reset to default 7

What Mr. Crockford means here is that you can implement specific functionality such as the on and fire functions that add event processing to any object by calling the function object that creates them (eventuality in this case) with that object as parameter.

The "part" here is an "event processing part" embodied in the eventuality function object. You could imagine different parts that add other functions. The idea here is that you can use this system to add this functionality to individual objects where you need it. This concept is called a Mixin(1).

Also read the final paragraph of chapter 5:

In this way a constructor could assemble objects from a set of parts. JavaScript's loose typing is a big benefit here because we are not burdened with a type system that is concerned about the lineage of classes.

(1) Thank you Zecc.

As I understand it, the point of this section of the book is to illustrate the power of JavaScript - in that you could build an object with all the various 'powerful ponents of JavaScript' easily.

As he says

For example, we can make a function that can add simple event processing features to any object. It adds an on method, a fire method, and a private event registry

either way is possible. i'm a huge fan of the author and he's like a hero to me. anyway, one of the best feature javascript offers us is the dynamic object. we can create object(s) as when do we desire it.

The following is my own test result. If you copy the code and paste them to a file named 'test.js', then run it on the mand line by 'node test.js' (must have already installed node), you will get the same result. My effort is to show you how to make use of eventuality() by tracing the flow with self-explanatory ments.

The only place I don't understand is the line; "fund = this[func]" (with "???" as the ment). It seems that "func = registry[func]" makes more sense to me, since the registry object is where the handler is registered, not the eventuality function object (i.e., the 'this').

var eventuality = function(that) {
  var registry = {};
  that.fire = function(event) {
    var type = typeof event === 'string' ? event : event.type;
    console.log('fire(): fired on event, "' + type + '"');

    if (registry.hasOwnProperty(type)) {
      var array = registry[type];
      for (var i = 0; i < array.length; ++i) {
        var handler = array[i];
        console.log('fire(): handler found at loop ' + i);
        var func = handler.method;
        var pars = handler.parameters;
        if (typeof func === 'string') {
          console.log('fire(): the found func is a string');
          func = this[func]; // ???
        } else {
          // Invoke the handler with parameters.
          console.log('fire(): the found method is NOT a string');
          func.apply(this, [pars]);
        }
      }
    }
    return this;
  };

  that.on = function(type, method, parameters) {
    // Register an event. Make a handler record. Put it in a handler array, making
    // one if it doesn't yet exist for this type.
    var handler = {
      method: method,
      parameters: parameters
    };
    if (registry.hasOwnProperty(type)) {
      // If already registered:
      registry[type].push(handler);
    } else {
      // If it's first time:
      console.log('on(): "' + type + '" event registered');
      registry[type] = [handler];
    }
    return this;
  }

  return that;
};

var dog_is_hungry = {
  type: 'is_hungry'
};
var dog_needs_to_poo = {
  type: 'needs_to_poo'
};
var dog_methods = {
  feed: function() {
    console.log('Event processed by the handler, dog_methods.feed(): ');
    for (var i = 0; i < arguments.length; ++i) {
      console.log('    Feed the dog with the "' + arguments[i].food + '"');
    }
  },
  walk: function() {
    console.log('Event processed by the handler, dog_methods.walk(): ');
    for (var i = 0; i < arguments.length; ++i) {
      console.log('    Walk the dog to the "' + arguments[i].place + '"');
    }
  }
};
var myDog = {
  name: 'Lucky',
  age: 2
}

var myDogEHM = eventuality(myDog); // EHM - events handling manager
console.log('My dog is named ' + myDogEHM.name);
console.log('My dog is aged ' + myDogEHM.age);

// Register the event-handlers
myDogEHM.on(dog_is_hungry.type, dog_methods.feed, {
  food: 'rice and meat'
});
myDogEHM.on(dog_needs_to_poo.type, dog_methods.walk, {
  place: 'park'
});

// Events to be handled
myDogEHM.fire(dog_is_hungry);
myDogEHM.fire(dog_needs_to_poo);

The following is the output:

My dog is named Lucky
My dog is aged 2
on(): "is_hungry"
event registered
on(): "needs_to_poo"
event registered
fire(): fired on event, "is_hungry"
fire(): handler found at loop 0
fire(): the found method is NOT a string
Event processed by the handler, dog_methods.feed():
  Feed the dog with the "rice and meat"
fire(): fired on event, "needs_to_poo"
fire(): handler found at loop 0
fire(): the found method is NOT a string
Event processed by the handler, dog_methods.walk():
  Walk the dog to the "park"

I have further modified Daniel C Deng's example, to further explain the use of this[func]. This code runs in the JavaScript console in Chrome.

var eventuality = function(that) {
  var registry = {};
  that.fire = function(event) {
    var type = typeof event === 'string' ? event : event.type;
    console.log('fire(): fired on event, "' + type + '"');

    if (registry.hasOwnProperty(type)) {
      var array = registry[type];
      for (var i = 0; i < array.length; ++i) {
        var handler = array[i];
        console.log('fire(): handler found at loop ' + i);
        var func = handler.method;
        var pars = handler.parameters;
        if (typeof func === 'string') {
          console.log('fire(): the found func is a string');
          func = dog_methods_2[func];
          //javascript turn string into object reference.
          //https://stackoverflow./questions/10953303/javascript-interpret-string-as-object-reference
        }

        // Invoke the handler with parameters.
        //console.log('fire(): the found method is NOT a string');
        func.apply(this, [pars]);

      }
    }
    return this;
  };

  that.on = function(type, method, parameters) {
    // Register an event. Make a handler record. Put it in a handler array, making
    // one if it doesn't yet exist for this type.
    var handler = {
      method: method,
      parameters: parameters
    };
    if (registry.hasOwnProperty(type)) {
      // If already registered:
      registry[type].push(handler);
    } else {
      // If it's first time:
      console.log('on(): "' + type + '" event registered');
      registry[type] = [handler];
    }
    return this;
  }

  return that;
};

var dog_is_hungry = {
  type: 'is_hungry'
};
var dog_needs_to_poo = {
  type: 'needs_to_poo'
};
var dog_is_thirsty = {
  type: 'needs_to_drink'
};
var dog_methods = {
  feed: function() {
    console.log('Event processed by the handler, dog_methods.feed(): ');
    for (var i = 0; i < arguments.length; ++i) {
      console.log('    Feed the dog with the "' + arguments[i].food + '"');
    }
  },
  walk: function() {
    console.log('Event processed by the handler, dog_methods.walk(): ');
    for (var i = 0; i < arguments.length; ++i) {
      console.log('    Walk the dog to the "' + arguments[i].place + '"');
    }
  },
  strings: ["drink"]
};
var dog_methods_2 = {
  drink: function() {
    console.log("    The dog drinks " + arguments[0].drink + ".");
  }
}
var myDog = {
  name: 'Lucky',
  age: 2
}

var myDogEHM = eventuality(myDog); // EHM - events handling manager
console.log('My dog is named ' + myDogEHM.name);
console.log('My dog is aged ' + myDogEHM.age);

// Register the event-handlers
myDogEHM.on(dog_is_hungry.type, dog_methods.feed, {
  food: 'rice and meat'
});
myDogEHM.on(dog_needs_to_poo.type, dog_methods.walk, {
  place: 'park'
});

// Events to be handled
myDogEHM.fire(dog_is_hungry);
myDogEHM.fire(dog_needs_to_poo);

myDogEHM.on(dog_is_thirsty.type, dog_methods.strings[0], {
  drink: 'water'
});
myDogEHM.fire(dog_is_thirsty);

This is the output:

My dog is named Lucky
My dog is aged 2
on(): "is_hungry" event registered
on(): "needs_to_poo" event registered
fire(): fired on event, "is_hungry"
fire(): handler found at loop 0
Event processed by the handler, dog_methods.feed(): 
    Feed the dog with the "rice and meat"
fire(): fired on event, "needs_to_poo"
fire(): handler found at loop 0
Event processed by the handler, dog_methods.walk(): 
    Walk the dog to the "park"
on(): "needs_to_drink" event registered
fire(): fired on event, "needs_to_drink"
fire(): handler found at loop 0
fire(): the found func is a string
    The dog drinks water.
发布评论

评论列表(0)

  1. 暂无评论