Unicode

2016-05-07 00:00:00 +0000

Unicode

Unicode 是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案

Unicode

ASCII 码

ASCII(American Standard Code for Information Interchange,美国标准信息交换代码)。

二进制(bit)有 0、1 两种状态。八个是一个字节(byte),有 256 种状态。

常用对照表

UTF

UTF,是 Unicode Transformation Format 的缩写,意为 Unicode 转换格式。

UTF-8(变长的编码方式)

UTF-8(8-bit Unicode Transformation Format)是一种针对 Unicode 的可变长度字符编码。

UTF-8的编码规则很简单,只有二条:

  • 1)对于单字节的符号,字节的第一位设为 0,后面 7 位为这个符号的 unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。
  • 2)对于 n 字节的符号(n>1),第一个字节的前 n 位都设为 1,第 n+1 位设为 0,后面字节的前两位一律设为 10。剩下的没有提及的二进制位,全部为这个符号的 unicode 码。

UTF-8 编码规则:

Unicode 符号范围 | UTF-8 编码方式
(十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx | 7
0000 0080-0000 07FF | 110xxxxx 10xxxxxx | 11
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx | 16 0x10000
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | 21 0x200000

JavaScript 下的操作:

'严'.charCodeAt(0).toString(16) // "4e25" 100111000100101
encodeURI('严') // "%E4%B8%A5" 111001001011100010100101
01234567 01234567 01234567 01234567 01234567
11100100 10111000 10100101 1001110 00100101

即,unicode 不够 16 位的,前面补 0。因为这个「严」在 FFFF 这个范围内,选第三个,1110xxxx 10xxxxxx 10xxxxxx 可以用来接受 16 位的值。

| 1110 0100 | 10 1110 00 | 10 100101 |

Others

UTF-16(字符用两个字节或四个字节表示)和UTF-32(字符用四个字节表示)。

ES6

说明:

  • ES6 提供了 codePointAt、String.fromCodePoint 方法。
  • 可以用 for…of 正确打印。

ES6 Unicode 详细介绍:

JavaScript 允许采用 \uxxxx 形式表示一个字符,其中“xxxx”表示字符的码点。

"\uD842\uDFB7"
// "𠮷"

"\u20BB7"
// " 7"

但是,这种表示法只限于 \u0000——\uFFFF 之间的字符,超出的要用双字节。

ES6 可以

"\u{20BB7}"
// "𠮷"

"\u{41}\u{42}\u{43}"
// "ABC"

let hello = 123;
hell\u{6F} // 123

'\u{1F680}' === '\uD83D\uDE80'
// true

JavaScript 共有 6 种方法可以表示一个字符

'\z' === 'z'  // true
'\172' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true
'\u{7A}' === 'z' // true

汉字“𠮷”的码点是0x20BB7,UTF-16编码为0xD842 0xDFB7(十进制为55362 57271) ES6提供了codePointAt方法,能够正确处理4个字节储存的字符,返回一个字符的码点。

var s = '𠮷a';

s.codePointAt(0) // 134071
s.codePointAt(1) // 57271

s.charCodeAt(2) // 97

JavaScript将“𠮷a”视为三个字符,codePointAt方法在第一个字符上,正确地识别了“𠮷”,返回了它的十进制码点134071(即十六进制的20BB7)。在第二个字符(即“𠮷”的后两个字节)和第三个字符“a”上,codePointAt方法的结果与charCodeAt方法相同。codePointAt参数不正确,这时可以用for...of循环。

var s = '𠮷a';
for (let ch of s) {
  console.log('unicode', ch.codePointAt(0).toString(16));
  console.log('string', ch);
}
// unicode 20bb7
// string 𠮷
// unicode 61
// string a

ES5提供String.fromCharCode不能识别 32 位的 UTF-16 字符。溢出,最高位被舍弃了。

String.fromCharCode(0x20BB7)
// "ஷ"

ES6提供了String.fromCodePoint方法,可以识别 0xFFFF 的字符。正好与codePointAt方法相反。

String.fromCodePoint(0x20BB7)
// "𠮷"
String.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y'
// true

References

npm 管理

2016-05-05 00:00:00 +0000

npm

$ npm install <packageName> --force # 强制安装
$ npm update <packageName> # 更新
$ npm install -g # 全局安装
$ npm help <command> # 可查看某条命令的详细帮助
$ npm ls <packageName> # 查看特定package的信息
$ npm info <packageName> # 输出的信息非常详尽,包括作者、版本、依赖等。
$ npm search <packageName> # 搜索

使用 npm shrinkwrap 来管理项目依赖

作用:可以让 node_modules 里面文件的依赖关系就按锁那样去依赖,哪个包里面版本是什么,就装对应的版本。执行命令将产生 npm-shrinkwrap.json 文件,与 Ruby 的 Gemfile 类似。

目的:npm 2 与 npm 3 安装同一个包结果不太一样,npm 3 会尽量平铺(官方说法是为了解决 windows 包目录太深的问题,然后我就好奇为啥用 windows 开发 node 相关的应用了),而 npm 2 包的依赖是按照层级关系去处理的。

当然我们可以用 npm dedupe 从

a
+-- b <-- depends on c@1.0.x
|   `-- c@1.0.3
`-- d <-- depends on c@~1.0.9
    `-- c@1.0.10

变成

a
+-- b
+-- d
`-- c@1.0.10

shrinkwrap 命令:

$ npm shrinkwrap # 可以锁住安装的包,安装的依赖目录。

.npmrc

为了管理 npm config。

npm run scripts

为了方便统一用 npm 运行。

nvm

使用 nvm use 如果当前目录下有 .nvmrc 文件,将改变当前的 shell 使用的 node 版本。

.nvmrc 内容如:

4.2.6

在 .zshrc 或 .bashrc 文件里面可以写一段 shell 命令,跳转到某个目录下的时候,可以顺便切换当前目录下的 node 版本。.rvmrc 是可以自动做到切换目录就更改了 rails 的版本,但 .nvmrc 做不到,所以以下为 hack 的内容:

# nvm: 管理 node 版本
export NVM_DIR=~/.nvm
source $(brew --prefix nvm)/nvm.sh
# Calling nvm use automatically in a directory with a .nvmrc file
autoload -U add-zsh-hook
load-nvmrc() {
  if [[ -f .nvmrc && -r .nvmrc ]]; then
    nvm use
  fi
}
add-zsh-hook chpwd load-nvmrc # When using cd
load-nvmrc # when using command-d which is opening a new window

References

《师傅》观后感

2016-05-02 00:00:00 +0000

https://movie.douban.com/review/7877003/

2016.05.02

这是一个腐败的江湖,江湖烂了,人也烂了,像一潭死水。

迂腐的规矩是这个江湖赖以生存的屏障,也是这个江湖没落的原因之一,当然主要原因仍然是时代,时代不在拳法,则拳法也渐消亡,优秀的人才都投身于其他行业去了呢。

老师不教真的,一生只真传两人,算得了什么老师。学生也没有什么素质,说谢师宴就谢师宴。谢师宴就是打赢了师傅,师傅请客。『谢师礼是被禁止的,因为拳师是社会名人,输不起。』

影片中小徐佳(师娘)是有情有义的,『他犯的事,我担着』这是『天津女人的好,你接不住』呢。当然这前提是因为师傅也是有情有义的,虽说他一开始是想利用徒弟,『毁了一个天才,成就一个门派』。门派最终也都是假的啊,毕竟没有真传的东西了,一个面子工程有什么意义呢。徒弟死了,徒弟本来应该是有伤无残,就是为了赌一口气,可是他是『一个门派的全部未来』啊,徒弟在年轻时已经超出师傅啦,假以十年肯定青出于蓝。而师傅的情义就是为徒弟报仇。如果师傅可以带着师娘徒弟逃走,『老规矩,逃了就等于死了』。

『毁了一个天才,成就一个门派』徒弟的毁也仅仅只是有伤无残,逐出天津,天津的前途尽毁,可是有一身本事,这样的买卖,虽有不甘,但师傅对徒弟也是有知遇之恩,栽培之意,师傅有恶评,但不伤大体,无所谓,还能算不超过底线。只是徒弟死了,这又是另一回事了。

『面包免费,但要先点菜。这么简单的道理我居然才明白。』别人帮你那么多,别人肯定要获得什么,对人家来说,他的声望更值钱,其他的都可以不在意,传承啊后人之事啊都不重要,所以为了声望可更过分,下狠手。

『她童年时受穷,当然会很自私。但男人的钱不就是用来给女人骗的吗?』这算是经典之言了。这是爱也是气概。

徒弟是真死了,他的死讯是从脚夫老大口中说的,他的大才,很难死的。大才,意志坚韧,三年本事,一年可学成。开头是徒弟打第八家武馆,打赢了喝咖啡。脚夫老大说埋了,就是真的埋了,没有必要撒这样的谎。

『能取你扣子,就能断你喉咙』

『好在是个小人,毁了,不可惜』小人是小人物,也就是贫民。毁了指背井离乡。

不管是武行还是脚行,都是平民百姓,市井小人,比不得政界军界。

有人说陈识是叶问的师傅,有人说陈识是叶问的师兄,有人说陈识是叶问。

随便教的徒弟就能踢人家八家武馆,说明师傅了得。『这是一个“出师父不出徒弟”的时代,各派都有名师,都后继无人。』

想到现在国内的很多开发者大会,大家都是把很多好像核心技术的东西藏着掖着,而国外的开发者大会交流技术就是真的交流,没有什么留一手。我朋友参加完新加坡 blackhat 后回来跟我讲的。

看完小说《师傅》,觉得电影比小说精彩。小说链接:https://www.douban.com/note/492185228/

好看的电影是不是因为看不太懂,打了星,点了赞发现意犹未尽,遥想那江湖,不曾有念想,『你更漂亮,我不敢动一点心』。

原则

2016-04-24 00:00:00 +0000

只讨论,不争论

  • 争论:为了说服别人。
  • 讨论:为了知道自己的不足。

Warning:至于别人最后是不是坚持己见,不愿意做改变,那是别人的事。

ES6(一)

2016-04-24 00:00:00 +0000

阅读阮一峰老师的《ECMAScript 6入门》

let 和 const

  1. temporal dead zone 为了防止运行时错误,防止在变量声明前就使用了这个变量,从而导致意料之外。
  2. let 块级作用域可以减少很多潜在的危害,比如说 for 循环里定义的 i,还有 switch 里定义的变量,出了这一块作用域就不应该被用到。
1
2
3
4
5
6
7
{
	let insane = 'Hello World0'; console.log('0', insane);
	{
		let insane = 'Hello World1'; console.log('1', insane);
	}
	console.log('2', insane);
}

ES6 的函数作用域也是块级作用域。

const 命令只是保证变量名指向的地址不变,并不保证该地址的数据不变。 有坑,如果

1
2
3
4
5
6
7
const foo = {};
foo.prop = 123;

const a = [];
a.push("Hello"); // 可执行
a.length = 0;    // 可执行
a = ["Dave"];    // 报错

可以用 const foo = Object.freeze({});

对象属性彻底冻结

1
2
3
4
5
6
7
8
let constantize = (obj) => {
	Object.freeze(obj);
	Object.keys(obj).forEach( (key, value) => {
		if ( typeof obj[key] === 'object' ) {
			constantize( obj[key] );
		}
	});
};

不能使用圆括号

  • 变量生命语句种,不能带有圆括号
  • 函数参数中,模式不能带有圆括号
  • 赋值语句中,不能将整个模式,或嵌套模式中的一层,防止圆括号之中

变量的解构赋值总结

  • 数组的解构赋值
  • 对象
  • 字符串
  • 数值和布尔值
  • 函数参数
  • 圆括号
  • 用途

Unicode

"\u0061"
// "a"

PS: 编码问题是一个比较大的坑,占坑不说 http://es6.ruanyifeng.com/#docs/string

正则

第一个参数是正则对象,第二个参数是指定修饰符。

new RegExp(/abc/ig, 'i').flags

四个字节的 UTF-16 需要使用 u 修饰符。

点(.)字符在正则表达式中,表示的是除了换行符(\n)外的任意单个字符。但是对于码点大于 0xFFFF 的 Unicode 字符,点字符不能识别,必须加上 u 修饰符。

var s = '𠮷';
/^.$/.test(s) // false
/^.$/u.test(s) // true

大括号可以表示 Unicode 字符

/\u{61}/.test('a') // false
/\u{61}/u.test('a') // true

\s 匹配所有空格字符,\S 预定义模式,匹配所有不是空格的字符,加了 u 修饰符才能正确匹配码点大于 0xFFFF 的 Unicode 字符。

function codePointLength(text) {
	var result = text.match(/[\s\S]/gu);
	return result ? result.length : 0;
}

var s = '𠮷𠮷';

s.length // 4
codePointLength(s) // 2

i 修饰符:大小写不敏感的匹配。

y 修饰符:我理解的是变成 /^xx/ 的正则表达式。

// 没有找到匹配
'x##'.split(/#/y)
// [ 'x##' ]

// 找到两个匹配
'##x'.split(/#/y)
// [ '', '', 'x' ]

'##x'.split(/^#/)
// ["", "#x"]

'##x'.split(/^#/g)
// ["", "#x"]

flags属性

// ES5的source属性
// 返回正则表达式的正文
/abc/ig.source
// "abc"

// ES6的flags属性
// 返回正则表达式的修饰符
/abc/ig.flags
// 'gi'

字符串转义

function escapeRegExp(str) {
  return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
}

let str = '/path/to/resource.html?search=query';
escapeRegExp(str)

JavaScript 只支持先行断言与先行否定断言,不支持后行断言(lookbehind)和后行否定断言。 『先行断言(lookahead)』指的是,x 只有在 y 前面才匹配,必须写成 /x(?=y)/。 『先行否定断言(negative lookahead)』/x(?!y)/。

/\d+(?=%)/.exec('100% of US presidents have been male')  // ["100"]
/\d+(?!%)/.exec('that’s all 44 of them')                 // ["44"]

『experiment JavaScript features』开关 enable(地址栏:about:flags) 『后行断言』,x 只有在 y 后面才匹配,必须写成 /(?<=y)x/。

/(?<=\$)\d+/.exec('Benjamin Franklin is on the $100 bill')  // ["100"]
/(?<!\$)\d+/.exec('it’s is worth about €90')                // ["90"]

数值的扩展

严格模式下,八进制不再允许使用前缀 0 表示,可以用 0o。 二进制,八进制前缀分别为 0b(或0B)和0o(或0O)。 可用 Number 方法转为十进制。

// Number.isFinite
(function (global) {
  var global_isFinite = global.isFinite;

  Object.defineProperty(Number, 'isFinite', {
    value: function isFinite(value) {
      return typeof value === 'number' && global_isFinite(value);
    },
    configurable: true,
    enumerable: false,
    writable: true
  });
})(this);

// Number.isNaN()
(function (global) {
  var global_isNaN = global.isNaN;

  Object.defineProperty(Number, 'isNaN', {
    value: function isNaN(value) {
      return typeof value === 'number' && global_isNaN(value);
    },
    configurable: true,
    enumerable: false,
    writable: true
  });
})(this);

在JavaScript内部,整数和浮点数是同样的储存方法,所以 3 和 3.0 被视为同一个值。

// Number.isInteger()
(function (global) {
  var floor = Math.floor,
    isFinite = global.isFinite;

  Object.defineProperty(Number, 'isInteger', {
    value: function isInteger(value) {
      return typeof value === 'number' && isFinite(value) &&
        value > -9007199254740992 && value < 9007199254740992 &&
        floor(value) === value;
    },
    configurable: true,
    enumerable: false,
    writable: true
  });
})(this);

Number.EPSILON 一个接受误差的范围。

0.1 + 0.2 - 0.3 < Number.EPSILON
// true

误差检查函数

function withinErrorMargin (left, right) {
  return Math.abs(left - right) < Number.EPSILON;
}
withinErrorMargin(0.1 + 0.2, 0.3)
// true
withinErrorMargin(0.2 + 0.2, 0.3)
// false

JavaScript 能够准确表示的整数范围在 -2^53 到 2^53 之间,(不含端点值)。

Math.pow(2, 53) // 9007199254740992

9007199254740992  // 9007199254740992
9007199254740993  // 9007199254740992

Math.pow(2, 53) === Math.pow(2, 53) + 1

// but
9007199254740994 // 9007199254740994
Math.pow(2, 53) + 2 // 9007199254740994

ES6引入了Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER这两个常量,用来表示这个范围的上下限。Number.isSafeInteger() 则是用来判断一个整数是否落在这个范围之内。

Number.isSafeInteger = function (n) {
  return (typeof n === 'number' &&
    Math.round(n) === n &&
    Number.MIN_SAFE_INTEGER <= n &&
    n <= Number.MAX_SAFE_INTEGER);
}

Notice:

Number.isSafeInteger(9007199254740993)
// false
Number.isSafeInteger(990)
// true
Number.isSafeInteger(9007199254740993 - 990)
// true
9007199254740993 - 990
// 返回结果 9007199254740002
// 正确答案应该是 9007199254740003

Math 扩展

  • Math.trunc 去除一个数的小数部分,返回整数部分。
  • Math.sign() 判断一个数到底是正数、负数还是零。
  • Math.cbrt 计算一个数的立方根。
  • Math.clz32() 返回32 位无符号整数形式有多少个前导 0。
  • Math.imul 返回两个数以32位带符号整数形式相乘的结果。(存疑)
  • Math.fround 返回一个数的单精度浮点数形式。
  • Math.hypot 返回所有参数的平方和的平方根。

对数

  • Math.expm1 返回 e^x - 1 即 Math.exp(x) - 1。
  • Math.log1p 返回 1 + x 的自然对数即 Math.log(1 + x)。
  • Math.log10 返回以 10 为底的 x 的对数。
  • Math.log2 返回以 2 为底的 x 的对数。

三角函数

  • Math.sinh(x) 返回x的双曲正弦(hyperbolic sine)
  • Math.cosh(x) 返回x的双曲余弦(hyperbolic cosine)
  • Math.tanh(x) 返回x的双曲正切(hyperbolic tangent)
  • Math.asinh(x) 返回x的反双曲正弦(inverse hyperbolic sine)
  • Math.acosh(x) 返回x的反双曲余弦(inverse hyperbolic cosine)
  • Math.atanh(x) 返回x的反双曲正切(inverse hyperbolic tangent)

指数运算

2 ** 2 // 4
2 ** 3 // 8

let a = 2;
a **= 2 // a = a * a
let b = 3;
b **= 3; // b = b * b * b

数组的扩展

Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map)。 用 Array.of() 来替代 Array() 还有 new Array()。 数组实例 copyWithin,将指定位置的成员复制到其他位置。

find 用于找出第一个符合条件的数组成员。findIndex 返回的是位置。用法相同。

[1, 5, 10, 15].find(function(value, index, arr) {
  return value > 9;
}) // 10

识别数组的NaN

[NaN].indexOf(NaN)
// -1

[NaN].findIndex(y => Object.is(NaN, y))
// 0

数组有 entries,keys,values 方法。与 for…of 配合使用。

数组 includes 方法,有语义化。

Map 结构的 has 方法,可以用来查找键名。

Set 结构的 has 方法,用来查找值。

Array(3) 返回一个具有3个空位的数组,空位没有任何值,不是 undefined。

ES5 forEach(), filter(), every() 和some()都会跳过空位。 map()会跳过空位,但会保留这个值 join()和toString()会将空位视为undefined,而undefined和null会被处理成空字符串。

0 in [undefined, undefined, undefined] // true
0 in [, , ,] // false

// forEach方法
[,'a'].forEach((x,i) => log(i)); // 1

// filter方法
['a',,'b'].filter(x => true) // ['a','b']

// every方法
[,'a'].every(x => x==='a') // true

// some方法
[,'a'].some(x => x !== 'a') // false

// map方法
[,'a'].map(x => 1) // [,1]

// join方法
[,'a',undefined,null].join('#') // "#a##"

// toString方法
[,'a',undefined,null].toString() // ",a,,"

ES6则是明确将空位转为 undefined。

由于空位的处理规则非常不统一,所以建议避免出现空位。

函数的扩展

参数设置默认值,ES6 的方式更为友好,简洁。

双重默认值,因为不能省略第二个参数。

function fetch(url, { method = 'GET' } = {}) {
  console.log(method);
}

fetch('http://example.com')

// 写法一
function m1({x = 0, y = 0} = {}) {
  return [x, y];
}

// 写法二
function m2({x, y} = {x: 0, y: 0}) {
  return [x, y];
}

函数的 length 属性将返回没有指定默认值的参数个数。 rest 参数也不会记入 length 属性

(function(...args) {}).length // 0

设置了默认值的参数与其之后的参数不记入 length。

如果函数 A 的参数默认值是函数 B,由于函数的作用域是其声明时所在的作用域,那么函数 B 的作用域不是函数 A,而是全局作用域。

使用 rest 参数(…变量名),就不需要使用 arguments。

// arguments
function sortNumbers() {
  return Array.prototype.slice.call(arguments).sort();
}

// rest
const sortNumbers = (...numbers) => numbers.sort();

rest 参数只能作为最后一个参数。

// ES5
Math.max.apply(null, [14, 3, 77]);
// ES6
Math.max(...[14, 3, 77]);

Math.max(14, 3, 77);

// ES5
new (Date.bind.apply(Date, [null, 2015, 1, 1]));
//ES6
new Date(...[2015, 1, 1]);

用来合并数组更简单。

结构函数

const [first, ...rest] = [1, 2, 3, 4, 5];

返回多个值的时候可以用解构函数。

可以将字符串转为真正的数组。

Map & Generator

let map = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]);
let arr = [...map.keys()];

var go = function*() {
  yield 1;
  yield 2;
  yield 3;
};
[...go()];

注意:没有 iterator 接口的对象,不能使用扩展运算符(…values)

(new Function).name // "anonymous"

// ES5,ES6 不一样。
var func1 = function() {};
// ES5
func1.name // ''
// ES6
func1.name // 'func1'

// ES5,ES6 一样。
const bar = function baz() {}
// ES5
bar.name // 'baz'
// ES6
bar.name // 'baz'

function foo () {}
foo.bind({}).name; // 'bound foo'

(function(){}).bind({}).name; // 'bound'

箭头函数,注意事项

  • 函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。
  • 不可以当作构造函数,也就是说,不可以使用 new 命令。
  • 不可以使用 arguments 对象,可以用 rest 参数替代。
  • 不可以使用 yield 命令,箭头函数不能用作 Generator 函数。

sample:

function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

var id = 21;

foo.call({ id: 42 });
// id: 42

普通函数,执行时 this 应该指向全局对象 window,这时应该输出 21。但是,箭头函数导致 this 总是指向函数定义生效时所在的对象(本例是{id: 42}),所以输出的是 42。

function Timer() {
  this.s1 = 0;
  this.s2 = 0;
  // 箭头函数
  setInterval(() => this.s1++, 1000);
  // 普通函数
  setInterval(function () {
    this.s2++;
  }, 1000);
}

var timer = new Timer();

setTimeout(() => console.log('s1: ', timer.s1), 3100);
setTimeout(() => console.log('s2: ', timer.s2), 3100);
// s1: 3
// s2: 0

利用参数默认值,可以指定某一个参数不得省略,如果省略就抛出错误。

function throwIfMissing() {
  throw new Error('Missing parameter');
}

function foo(mustBeProvided = throwIfMissing()) {
  return mustBeProvided;
}

foo()
// Error: Missing parameter

foo(123)
// 123

参数的默认值不是在定义时执行,而是在运行时执行(即如果参数已经赋值,默认值中的函数就不会运行)。可以讲参数默认值设为 undefined,表明参数可省略。

console.log(...[1, 2, 3])
// 1 2 3

扩展运算符取代 apply 方法:

// ES5 写法
Math.max.apply(null, [14, 3, 77]);

// ES6 写法
Math.max(...[14, 3, 77]);

// 等同于
Math.max(14, 3, 77);

push 写法:

// ES5
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
Array.prototype.push.apply(arr1, arr2);

// ES6
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1.push(...arr2);

Date 相关的:

// ES5
new (Date.bind.apply(Date, [null, 2015, 1, 1]));

// ES6
new Date(...[2015, 1, 1]);

Others

[1, 2].concat(more);
[1, 2, ...more];

注意:扩展运算符用于数组赋值,只能放在参数的最后一位。

// 字符串转数组
[...'hello'];

// 能识别 32 位 Unicode 字符
'x\uD83D\uDE80y'.length // 4
[...'x\uD83D\uDE80y'].length // 3

function name

var func1 = function() {}
// ES5
func1.name // ''
// ES6
func1.name // 'func1'

const bar = function baz() {};
// ES5
bar.name // "baz"
// ES6
bar.name // "baz"

(new Function).name // "anonymous"

function foo() {};
foo.bind({}).name // "bound foo"
(function(){}).bind({}).name // "bound "

continue ….

五个为什么

2016-04-17 00:00:00 +0000

如下示例解释的就是五问法的基本过程:

  • 我的汽车无法启动。(问题)
  1. 为什么?:电池电量耗尽。(第一个为什么)
  2. 为什么?:交流发电机不能正常工作。(第二个为什么)
  3. 为什么?:交流发电机皮带断裂。(第三个为什么)
  4. 为什么?:交流发电机皮带远远超出了其使用寿命,从未更换过。(第四个为什么)
  5. 为什么?:我一直没有按照厂家推荐的保养计划对汽车进行过保养和维护。(第五个为什么,根本原因)

解决问题的人要有“打破砂锅问到底”的精神。

https://en.wikipedia.org/wiki/5_Whys

读一本书需要花多少时间

2016-04-10 00:00:00 +0000

阅读

First:

书名 时间 字数
《微信帝国:张小龙的内争与外伐》 33分 11756字
《九败一胜》 6时24分 156806字
《打造 Facebook》 4时30分 111411字
《MacTalk 跨越边界》 7时3分 179144字
《时间简史(普及版)》 4时39分 38960字
《鱼羊野史(第 1 卷)》 8时38分 229964字
《xxx》 14分 8384字
《魔兽世界诞生记》 44分 21366字

Second:

书名 时间 字数
《小王子》 46分 36687字
《西游日记》 3时12分 101847字
《悟空传》 4时44分 132049字
《霍比特人》 4时36分 180808字
《xxx》 2时43分 119749字

Third:

书名 时间 字数
《鱼羊野史(1-4册)》 25时31分 908314字

Three Virtues

2016-04-02 00:00:00 +0000

Three Virtues

According to Larry Wall, the original author of the Perl programming language, there are three great virtues of a programmer; Laziness, Impatience and Hubris

  • Laziness: The quality that makes you go to great effort to reduce overall energy expenditure. It makes you write labor-saving programs that other people will find useful and document what you wrote so you don’t have to answer so many questions about it.
  • Impatience: The anger you feel when the computer is being lazy. This makes you write programs that don’t just react to your needs, but actually anticipate them. Or at least pretend to.
  • Hubris: The quality that makes you write (and maintain) programs that other people won’t want to say bad things about.

http://threevirtues.com/

MacTalk 跨越边界

2016-03-28 00:00:00 +0000

最近在看 MacTalk 的《跨越边境》,这是一本对我来说很值得拜读的书,给我启发很大,在这摘录了一些有意思的片段。

webpack

2016-03-22 00:00:00 +0000

webpack 主要是为了解决打包的问题。