ECMAScript 6学习(四)

本人是android开发的,由于最近React Native的火热,再加上自己完全不懂JS的语法,俗话说的好"落后就要挨打",虽然不知道谁说的,不过很有道理.

学习书籍《ECMAScript 6 入门 》

各种类型的扩展


正则的扩展

RegExp构造函数

第一种情况是,参数是字符串,这时第二个参数表示正则表达式的修饰符(flag)

var regex = new RegExp('xyz', 'i');

// 等价于

var regex = /xyz/i;

第二种情况是,参数是一个正则表示式,这时会返回一个原有正则表达式的拷贝。

var regex = new RegExp (/xyz/i);

// 等价于

var regex = /xyz/i;

但是,ES5不允许此时使用第二个参数,添加修饰符,否则会报错。

var regex = new RegExp (/xyz/, 'i');

// Uncaught TypeError: Cannot supply flags when constructing one RegExp from another

ES6改变了这种行为。如果RegExp构造函数第一个参数是一个正则对象,那么可以使用第二个参数指定修饰符。而且,返回的正则表达式会忽略原有的正则表达式的修饰符,只使用新指定的修饰符。

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

// "i"

上面代码中,原有正则对象的修饰符是 ig,它会被第二个参数 i 覆盖。

u修饰符

ES6对正则表达式添加了u修饰符,含义为“Unicode模式”,用来正确处理大于\uFFFF的Unicode字符。也就是说,会正确处理四个字节的UTF-16编码。

一旦加上u修饰符号,就会修改下面这些正则表达式的行为。

var s = '𠮷';

/^.$/.test(s)

// false

/^.$/u.test(s)

// true

上面代码表示,如果不添加u修饰符,正则表达式就会认为字符串为两个字符,从而匹配失败。

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

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

/\u{20BB7}/u.test('𠮷') // true

上面代码表示,如果不加u修饰符,正则表达式无法识别\u{61}这种表示法,只会认为这匹配61个连续的u

使用u修饰符后,所有量词都会正确识别码点大于0xFFFF的Unicode字符。

/a{2}/.test('aa') // true

/a{2}/u.test('aa') // true

/𠮷{2}/.test('𠮷𠮷') // false

/𠮷{2}/u.test('𠮷𠮷') // true

有些Unicode字符的编码不同,但是字型很相近,比如,\u004B\u212A都是大写的K

/[a-z]/i.test('\u212A') // false

/[a-z]/iu.test('\u212A') // true

上面代码中,不加u修饰符,就无法识别非规范的K字符。

y 修饰符

除了u修饰符,ES6还为正则表达式添加了y修饰符,叫做“粘连”(sticky)修饰符。

y修饰符的作用与g修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。不同之处在于,g修饰符只要剩余位置中存在匹配就可,而y修饰符确保匹配必须从剩余的第一个位置开始,这也就是“粘连”的涵义。

var s = 'aaa_aa_a';

var r1 = /a+/g;

var r2 = /a+/y;

r1.exec(s) // ["aaa"]

r2.exec(s) // ["aaa"]

r1.exec(s) // ["aa"]

r2.exec(s) // null

上面代码有两个正则表达式,一个使用g修饰符,另一个使用y修饰符。这两个正则表达式各执行了两次,第一次执行的时候,两者行为相同,剩余字符串都是_aa_a。由于g修饰没有位置要求,所以第二次执行会返回结果,而y修饰符要求匹配必须从头部开始,所以返回null

y修饰符相匹配,ES6的正则对象多了sticky属性,表示是否设置了y修饰符。

var r = /hello\d/y;

r.sticky // true

ES6为正则表达式新增了flags属性,会返回正则表达式的修饰符。

// ES5的source属性

// 返回正则表达式的正文

/abc/ig.source

// "abc"

// ES6的flags属性

// 返回正则表达式的修饰符

/abc/ig.flags

// 'gi'

目前,有一个提案,引入了一种新的类的写法\p{...}\P{...},允许正则表达式匹配符合Unicode某种属性的所有字符。

由于Unicode的各种属性非常多,所以这种新的类的表达能力非常强。

const regex = /^\p{Decimal_Number}+$/u;

regex.test('𝟏𝟐𝟑𝟜𝟝𝟞𝟩𝟪𝟫𝟬𝟭𝟮𝟯𝟺𝟻𝟼') // true

上面代码中,属性类指定匹配所有十进制字符,可以看到各种字型的十进制字符都会匹配成功。

\p{Number}甚至能匹配罗马数字。

// 匹配所有数字

const regex = /^\p{Number}+$/u;

regex.test('²³¹¼½¾') // true

regex.test('㉛㉜㉝') // true

regex.test('ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ') // true

数值的扩展

ES6 提供了二进制和八进制数值的新的写法,分别用前缀0b(或0B)和0o(或0O)表示。

0b111110111 === 503 // true

0o767 === 503 // true

如果要将0b0o前缀的字符串数值转为十进制,要使用Number方法。

ES6引入了Number.MAX_SAFE_INTEGERNumber.MIN_SAFE_INTEGER这两个常量,用来表示这个范围的上下限。

Number.MAX_SAFE_INTEGER === Math.pow(2, 53) - 1

// true

Number.MAX_SAFE_INTEGER === 9007199254740991

// true

Number.MIN_SAFE_INTEGER === -Number.MAX_SAFE_INTEGER

// true

Number.MIN_SAFE_INTEGER === -9007199254740991

// true

Number.isSafeInteger()则是用来判断一个整数是否落在这个范围之内。

Number.isSafeInteger(3) // true

Number.isSafeInteger(1.2) // false

Number.isSafeInteger(9007199254740990) // true

Number.isSafeInteger(9007199254740992) // false

Number.isSafeInteger(Number.MIN_SAFE_INTEGER - 1) // false

Number.isSafeInteger(Number.MIN_SAFE_INTEGER) // true

Number.isSafeInteger(Number.MAX_SAFE_INTEGER) // true

Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1) // false

Math对象的扩展

Math.trunc()方法用于去除一个数的小数部分,返回整数部分。

Math.trunc(4.1)// 4

Math.sign()方法用来判断一个数到底是正数、负数、还是零。

它会返回五种值。

参数为正数,返回+1;

参数为负数,返回-1;

参数为0,返回0;

参数为-0,返回-0;

其他值,返回NaN。

Math.cbrt()方法用于计算一个数的立方根。

Math.clz32()方法返回一个数的32位无符号整数形式有多少个前导0.(JavaScript的整数使用32位二进制形式表示)。

Math.imul()方法返回两个数以32位带符号整数形式相乘的结果,返回的也是一个32位的带符号整数。

Math.imul(2, 4)  // 8

Math.imul(-1, 8)  // -8

Math.imul(-2, -2) // 4

Math.fround()方法返回一个数的单精度浮点数形式。

Math.fround(0)    // 0

Math.fround(1)    // 1

Math.fround(1.337) // 1.3370000123977661

Math.fround(1.5)  // 1.5

Math.fround(NaN)  // NaN

Math.hypot()方法返回所有参数的平方和的平方根。

Math.hypot(3, 4);        // 5

Math.hypot(3, 4, '5');  // 7.0710678118654755

Math.expm1(x)返回ex- 1,即Math.exp(x) - 1

等......太多了,放链接:

数值的扩展

数组的扩展

函数的扩展

1.rest参数

ES6 引入 rest 参数(形式为“...变量名”),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

rest 参数中的变量代表一个数组,所以数组特有的方法都可以用于这个变量。下面是一个利用 rest 参数改写数组push方法的例子。

function push(array, ...items) {

      items.forEach(function(item) {

                array.push(item);

                console.log(item);

       });

}

var a = [];

push(a, 1, 2, 3)

注意,rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。

// 报错

function f(a, ...b, c) {

// ...

}

函数的length属性,不包括 rest 参数。

(function(a) {}).length  // 1

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

(function(a, ...b) {}).length  // 1


2.扩展运算符

扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。

任何Iterator接口的对象,都可以用扩展运算符转为真正的数组。

Map结构

let map = new Map([

   [1, 'one'],

   [2, 'two'],

   [3, 'three'],

]);

let arr = [...map.keys()]; // [1, 2, 3]

Generator函数运行后,返回一个遍历器对象,因此也可以使用扩展运算符。

var go = function*(){

     yield 1;

     yield 2;

      yield 3;

};

[...go()] // [1, 2, 3]

如果对没有iterator接口的对象,使用扩展运算符,将会报错。


3.lambda演算

箭头函数还有一个功能,就是可以很方便地改写λ演算

首先说一下 lambda演算;

lambda演算写法

λx.x + 2

使用JavaScript来写,如下:

(function(x) {    

   return x + 2;

}) ();

两个lambda合并写法

(λx.x*x)(λx.x+2)

让我们来算算看:

x = 3 时,λx.x*x 的 输出为 9

9 做为 λx.x+2 的 输入,成为 9 + 2,输出为 11

答案就是 11

(λx.x*x)(λx.x+2) 等于 9 + 2

箭头函数改写lambda演算 如下:

// λ演算的写法

fix = λf.(λx.f(λv.x(x)(v))) (λx.f(λv.x(x)(v)))

// ES6的写法

var  fix = f  => (x=>f(v=>x(x)(v)))

                       (x=>f(v=>x(x)(v)));

对象的属性的遍历

ES6一共有5种方法可以遍历对象的属性。

(1)for...in

for...in循环遍历对象自身的和继承的可枚举属性(不含Symbol属性)。

(2)Object.keys(obj)

Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性)。

(3)Object.getOwnPropertyNames(obj)

Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性)。

(4)Object.getOwnPropertySymbols(obj)

Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有Symbol属性。

(5)Reflect.ownKeys(obj)

Reflect.ownKeys返回一个数组,包含对象自身的所有属性,不管是属性名是Symbol或字符串,也不管是否可枚举。

以上的5种方法遍历对象的属性,都遵守同样的属性遍历的次序规则。

首先遍历所有属性名为数值的属性,按照数字排序。

其次遍历所有属性名为字符串的属性,按照生成时间排序。

最后遍历所有属性名为Symbol值的属性,按照生成时间排序。

Reflect.ownKeys({ [Symbol()]:0, b:0, 10:0, 2:0, a:0 })

// ['2', '10', 'b', 'a', Symbol()]

Null 传导运算符

编程实务中,如果读取对象内部的某个属性,往往需要判断一下该对象是否存在。比如,要读取message.body.user.firstName,安全的写法是写成下面这样。

const firstName = (message

&& message.body

&& message.body.user

&& message.body.user.firstName) || 'default';

这样的层层判断非常麻烦,因此现在有一个提案,引入了“Null 传导运算符”(null propagation operator)?.,简化上面的写法。

const  firstName = message?.body?.user?.firstName || 'default';

上面代码有三个?.运算符,只要其中一个返回nullundefined,就不再往下运算,而是返回undefined

“Null 传导运算符”有四种用法。

obj?.prop// 读取对象属性

obj?.[expr]// 同上

func?.(...args)// 函数或对象方法的调用

new C?.(...args)// 构造函数的调用

传导运算符之所以写成obj?.prop,而不是obj?prop,是为了方便编译器能够区分三元运算符?:(比如obj?prop:123)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容