ES6标准入门 学习笔记 (02)

72 阅读7分钟

引入

系统学习ES6各种特性,了解背后的原理。

笔记

1.字符串的扩展

1.1 Unicode表示法

JavaScript允许使用\uxxxx形式表示一个字符,但此方式仅限于\u0000~\uFFFF之间的字符。

如使用\u20BB7则会被视为\u20BB+'7',所以部分汉字需要两个字符(4个字节)才能表示

在ES6中可以使用\u{16进制数值}表示汉字,如\u{20BB7}解释为"𠮷"

1.2 codePointAt()

用4个字节表示的一个汉字在使用时会遇到长度问题。

let s = "𠮷"; //注意不是吉祥的吉,是\u{20BB7} 或者0xD842 0xDFB7 十进制为 55362 57271

s.length; // 2
s.charAt(0); // ' '
s.charAt(1); // ' '
s.charCodeAt(0); // 55362
s.charCodeAt(1); // 57271

ES6中提供了codePointAt()方法,能够正确处理4字节长度字符和2字节字符

(可以用来判断字符是否为4字节 或者说 32Bit)

但是,传入的参数依然是2字节字符所在的位置

let s = "𠮷a"
s.codePointAt(0); // 134071 𠮷对应的值
s.codePointAt(1); // 57271 𠮷后2字节对应的值
s.codePointAt(2); // 97 a对应的值

对于含有4字节字符的字符串,可以使用for...of遍历,能正确识别4字节字符

而传统的for循环无法识别4字节字符

1.3 fromCodePoint()

原来的String.fromCharCode()也不能识别32位数值,超出16位的部分会溢出而舍去

使用String.fromCodePoint()可以识别

String.fromCodePoint(0x20BB7); // '𠮷'
String.fromCharCode(0x20BB7); // 'ஷ'

1.4 includes()、startsWith()、endsWith()

传统上只有indexOf()方法能用来确定字符串是否包含于另一个字符串(返回bool)

ES6提供了新的方法(返回bool):

includes()startsWith()endsWith()

方法用途顾名思义,而且都有两个参数:字符串、开始搜索的位置

endsWith中表示在前n个字符中搜索,其他两个表示从第n个字符之后开始搜索)

1.5 repeat()

返回字符串重复n次后的新字符串

"123".repeat(2.9); // "123123" 对于小数会取整数部分、负数则会报错
"123".repeat(-0.1); // ""      0则为空
"123".repeat("2"); // "123123" 字符串会被转为数字

1.6 padStart()、padEnd()

用于补全字符串长度,分为头部补全和尾部补全

"x".padStart(5, "ab"); //"ababx" 
"xxx".padEnd(2, "ab"); // "xxx" 原字符串超过要补全到的长度时,返回原字符串
"xxx".padStart(10, "0123456789"); // "0123456xxx" 补全字符串过长时会截掉超出部分

//省略第二个参数时用空格补全

1.7 模板字符串

ES6中引入了模板字符串: 用反引号`来包围字符串

可以实现字符串中嵌入变量(使用${}包裹表达式来嵌入)、定义多行文本字符串

let word = "稀土掘金";
console.log(`!!!
juejin.cn: ${word}
!!!`)

/*
!!!
juejin.cn: 稀土掘金
!!!
*/

2.正则的扩展

2.1 RegExp构造函数

ES5中常用

var regex = new RegExp('xyz', 'i'); //使用字符串和模式两个参数
// 等价于
var regex = new RegExp(/xyz/i); //使用正则表达式为参数
// 等价于
var regex = /xyz/i;  //最简单的构造函数

var regex = new RegExp(/xyz/, 'i'); //报错,ES5中不允许混合使用

但ES6中若使用了第二参数会覆盖第一个参数正则表达式的模式

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

2.2 正则的使用方法

字符串对象中共有4个方法可以使用正则表达式:

  1. match()
  2. replace()
  3. search()
  4. split()

2.3 u修饰符

ES6为了解决4字节字符匹配的问题,增加了u修饰符,意为“Unicode模式”

同时正则表达式中的.在u模式下才会匹配4字节字符

使用ES6规则\u{}表示字符的正则表达式中,必须使用u模式才能正确转化为字符

3. 数值的扩展

3.1 二进制八进制

二进制使用0b开头,八进制使用0o开头

可以使用Number方法将二进制、八进制字符串转为十进制数值如Number('0b111')

3.2 isFinite()、isNaN()

ES6在Number对象上添加了两个方法,前者检查数值是否为有限的,后者检查是否为NaN

3.3 parseInt()、parseFloat()

用于将字符串转化为整数、浮点数

ES6将这两个全局的方法移植到了Number对象上,旨在使语言逐渐模块化

3.4 isInteger()

判断一个值是否为整数,注意js中整数和浮点数用相同的储存方式,所以3, 3.0都判断为整数

3.5 Math对象的扩展

  1. Math.trunc():去除一个数(非数值会先Number方法转为数字)的小数部分,返回整数部分。对于无法截取的内容返回NaN。
  2. Math.sign():判断一个数值(非数值会先转换)的符号(-1,+1,+0,-0,NaN)

3.6 指数运算符

ES6新增了指数运算符(**)

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

4.函数的扩展

4.1 函数参数的默认值

ES5中不能直接为函数设置默认值,只能用变通的方式

ES6中允许为函数设置默认值

function add(x=1,y=1){return x+y};
add(3); //4
  • 参数变量是默认声明的,注意不能再次使用letconst声明
  • 若需要使用默认参数时,每次使用都会重新计算表达式赋值(惰性求值)
  • 默认参数需要为尾参数,否则无法使用其默认值(除非显示地传入undefined
  • 函数的length属性表示函数预期传入多少个参数 = 总参数的数量 - 默认参数的数量
  • 函数默认值会在调用函数时形成一个作用域(在为默认参数赋值时的参数之间有一个作用域)
  • 可以设置默认参数默认值为undefined表示这个参数可以省略

4.2 rest参数

ES6中引入了函数的rest参数,形式为...变量名

可以将传入的一个或多个参数接收为一个数组

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

function sum(...values){
    let res = 0;
    for (let v of values){
        res+=v;
    }
    return res
}

4.3 name属性

函数有name属性

对于有具体函数名的变量,name属性返回具体的函数名

对于匿名函数,ES5中返回'',ES6中返回变量名

Function构造函数返回的函数实例,name属性为"anonymous"

bind返回的函数,name属性会带上bound前缀

4.4 箭头函数

ES6规定可以使用=>定义函数

但是注意几个地方:

  1. 箭头函数体内的this对象就是定义时所在的对象,而不是使用时所在的对象

这说明箭头函数中的this在定义时就被固定了,不会像function内一样发生改变。

这种特性非常有利于封装回调函数。

而且箭头函数没有自己的this,会默认绑定最外层this

    const obj = {
        a: function() { console.log(this) },
        b: {
            c: () => {console.log(this)},
            d: function() { console.log(this) }
            }
    }
    obj.a()   //function函数打出的是obj
    obj.b.c()  //浏览器中箭头函数打出的是window对象
    obj.b.d() //function函数打出的是obj.b
  1. 箭头函数不能当做构造函数(即不可以使用new命令)
  2. 不可以使用arguments对象(函数体内不存在该对象),可以用rest参数代替
  3. 不可以使用yield命令,因此不能用作Generator函数
let f = () => 5;

f = x => x+1; //单个参数时括号可以省略

f = (x,y)=>x+y; // 单个语句时 {}和return可以省略

f = (x,y)=>{  // 不省略的情况
    return x+y;
}

f = ()=> ({x:1,y:2}); // 直接返回对象时,为了避免和代码块混淆,外部加上圆括号

let valsToArr = (...vals)=>vals; //使用rest参数,注意要加括号

箭头函数的嵌套

箭头函数内还可以再使用箭头函数

let insert = val=> ({into: arr=> ({after: afterVal=>{
    // 可以使用嵌套过程中传入的变量
    arr.splice(arr.indexOf(afterVal)+1, 0, val); //在afterVal之后插入val
    return arr;
}})});
insert(2).into([1,3]).after(2); //[1,2,3]

部署管道机制(前一个函数的输出为后一个函数的输入)

const pipeline = (...funcs)=> val=> funcs.reduce((a,b)=>b(a),val); //返回函数组成的流水线

const plus1 = a=>a+1;
const mult2 = a=>2*a;

const addThenMult = pipeline(plus1, mult2);
addThenMult(5); //12