分类 学习 下的文章

用 Map 结构来实现此功能,Test Case 如下:

const ee = new EventEmmiter();

ee.on('e1', function() {
  console.log('trigger e1');
});

ee.on({
  e1: function() {
    console.log('trigger e11');
  },
  e2: function() {
    console.log('trigger e2');
  }
});

ee.trigger('e2');
ee.trigger('e2');
ee.trigger('e2');
ee.trigger('e1');

setTimeout(_ => {
  ee.off('e1');
  ee.off('e2');
}, 1000);

下面是源码的实现:

const _events = {};

const has = name => _events[name] !== void 0;

const hasOwn = (obj, key) => ({}.hasOwnProperty.call(obj, key));

const eachObject = (obj, cb) => {
  for (let key in obj) {
    if (hasOwn(obj, key)) {
      cb(key, obj[key]);
    }
  }
};

class EventEmmiter {
  on(name, handler) {
    if (typeof name === 'string') {
      if (typeof handler !== 'function') {
        throw new Error('handle must is function.');
      }

      if (has(name)) {
        _events[name].push(handler);
      } else {
        _events[name] = [handler];
      }
    } else if (typeof name === 'object') {
      eachObject(name, (key, handle) => {
        if (has(key)) {
          _events[key].push(handle);
        } else {
          _events[key] = [handle];
        }
      });
    }

    return () => {
      if (typeof name === 'string') {
        this.off(name);
      } else if (typeof name === 'object') {
        eachObject(name, key => {
          this.off(key);
        });
      }
    };
  }

  trigger(name, args = [], context = this) {
    const handlers = _events[name];
    if (handlers && handlers.length > 0) {
      handlers.forEach(handle => handle.call(context, args));
    }
  }

  off(name) {
    _events[name] = null;
    delete _events[name];
  }
}

如果要实际使用的话可以将判断 Object 替换为 is-plain-object 这个类库。

变量名的组成:

  1. 首字母 [a-zA-Z0-9_]
  2. 不能包含空格,能够使用下划线代替
  3. 不能使用关键字

变量的使用:

#define
url="https://www.so.com"

#readonly, 只读的不能修改
#如果修改:line <number>: url: readonly variable
readonly url

#销毁变量
unset url

#变量引用
echo "enter: $url"
echo "enter: ${url}"
#{} 主要用于确定变量的边界, 下面表示 $url, 而非 $url_site
echo "enter: ${url}_site"
#{} 边界在 $ 连续编写的时候不用,不过不推荐
#如果这样写的拖出去吧...
url1="url1"
url2="url2"
url3="url3"
echo $url1$url2$url3

变量的类型

  1. 局部变量,脚本当前作用域
  2. 环境变量,shell 具备访问环境变量的能力
  3. shell 变量,自己提供的,可以包括(1, 2)

shell 的特殊变量

这里主要是写点例子熟悉一下就行了。

echo "args length: $#"
echo "args length: ${#}"
for arg in $*;
  do
    echo "arg is: ${arg}"
  done

echo "----------------"

for var in "$*";
  do
    echo $var
  done

for var in "$@";
  do
    echo $var
  done
#执行
sh ./demo.sh 1 2 3
#输出
args length: 3
args length: 3
arg is: 1
arg is: 2
arg is: 3
----------------
1 2 3
1
2
3

例子中主要注意 $*$@ 的区别,区别在于用 "" 包裹的时候,其余情况一致,可以运行了试试。

其余的看一个表,$? 暂时不用管。

变量含义
$0当前脚本的文件名, 这里指执行的文件,比如 ./demo.sh => ./demo.sh
$n传入的参数,从 1 开始,一次类推,$* 能够访问所有的参数
$#参数的个数,length => 也是从 1 开始计数
$*所有参数
$@所有参数,区别见例子
$$当前进程的 pid
$?上次退出状态的返回值,也可以作为函数返回值

以下的测试例子都可以在 github 找到,但是最近好像不太稳定。
其实 ng2 在这方面做得挺好的,用起来也很简单,所以看完基本就可以动手写一写。强大并不止是这一方面,在写这些的过程中,通过一些配置,让开发很纯粹,有时间再录一个新手入门的开发教程。


- 阅读剩余部分 -

前言

今天有朋友问了 “KeyMirror” 这个库有什么用的问题,其实这个问题并不难,这里扫一下盲区。

会按照下面这个逻辑来展开,彻底理解一下:

  1. KeyMirror 有什么用?
  2. Google Closure Compiler 是什么?
  3. KeyMirror 解决了什么问题,好处是什么?
  4. KeyMirror 的源码是什么样子?
  5. 用 Gulp 配置一个压缩任务,测试一下 Google Closure Compiler.

- 阅读剩余部分 -