ES6 Note

变量的解构赋值

  • 如果等号的右边不是数组(或者严格地说,不是可遍历的结构,参见《Iterator》一章),那么将会报错。
    let [foo] = 1;
    let [foo] = false;
    let [foo] = NaN;
    let [foo] = undefined;
    let [foo] = null;
    let [foo] = {};

  • 解构赋值可以设置默认值
    let [x = 1] = [undefined];

  • 如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值。
    function f() {
    console.log('aaa');
    }
    let [x = f()] = [1];

  • 对象的解构赋值是看名字,而不是像数组一样看顺序。

  • 也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
    let { foo: baz } = { foo: "aaa", bar: "bbb" };
    baz // "aaa"
    foo // error: foo is not defined

  • 注意模式和变量的区分,模式不会被赋予值,变量会。
    {foo}={foo:'value'} 实际上等于 {foo(1):foo(2)}={foo:'value'}, 第一个foo是模式,第二个是变量.

  • 上面代码的写法会报错,因为 JavaScript 引擎会将{x}理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。
    错误的写法
    let x;
    {x} = {x: 1};
    // 正确的写法
    let x;
    ({x} = {x: 1});

  • 解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。
    let { prop: x } = undefined; // TypeError
    let { prop: y } = null; // TypeError

  • 注意这个例子
    function move({x = 0, y = 0} = {}) {
    return [x, y];
    }
    move({}); // [0, 0]
    move(); // [0, 0]

    ~~~~~~~~~~~~~~~~
    function move({x = 0, y = 0}) {
    return [x, y];
    }
    move({}); // [0, 0]
    move(); //报错

    ~~~~~~~~~~~~~~~~
    function move({x, y} = { x: 0, y: 0 }) {
    return [x, y];
    }
    move({x: 3, y: 8}); // [3, 8]
    move({x: 3}); // [3, undefined]
    move({}); // [undefined, undefined]
    move(); // [0, 0]

编码方式演进历史

  1. 中国人民通过对 ASCII 编码的中文扩充改造,产生了 GB2312 编码,可以表示6000多个常用汉字。
  2. 汉字实在是太多了,包括繁体和各种字符,于是产生了 GBK 编码,它包括了 GB2312 中的编码,同时扩充了很多。
  3. 中国是个多民族国家,各个民族几乎都有自己独立的语言系统,为了表示那些字符,继续把 GBK 编码扩充为 GB18030 编码。
  4. 每个国家都像中国一样,把自己的语言编码,于是出现了各种各样的编码,如果你不安装相应的编码,就无法解释相应编码想表达的内容。
  5. 终于,有个叫 ISO 的组织看不下去了。他们一起创造了一种编码 UNICODE ,这种编码非常大,大到可以容纳世界上任何一个文字和标志。所以只要电脑上有 UNICODE 这种编码系统,无论是全球哪种文字,只需要保存文件的时候,保存成 UNICODE 编码就可以被其他电脑正常解释。
  6. UNICODE 在网络传输中,出现了两个标准 UTF-8 和 UTF-16,分别每次传输 8个位和 16个位。于是就会有人产生疑问,UTF-8 既然能保存那么多文字、符号,为什么国内还有这么多使用 GBK 等编码的人?因为 UTF-8 等编码体积比较大,占电脑空间比较多,如果面向的使用人群绝大部分都是中国人,用 GBK 等编码也可以。
  7. UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度,当字符在ASCII码的范围时,就用一个字节表示,保留了ASCII字符一个字节的编码做为它的一部分,注意的是unicode一个中文字符占2个字节,而UTF-8一个中文字符占3个字节)。从unicode到utf-8并不是直接的对应,而是要过一些算法和规则来转换。
  8. 其实一个字符等于两个字节,一个字节是八位。
  9. 关于“全角”和“半角”:
    全角:是指中GB2312-80(《信息交换用汉字编码字符集·基本集》)中的各种符号。
    半角:是指英文件ASCII码中的各种符号。
    全角状态下字母、数字符号等都会占两个字节的位置,也就是一个汉字那么宽,半角状态下,字母数字符号一般会占一个字节,也就是半个汉字的位置,全角半角对汉字没有影响。

字符串的扩展

  • 字符串的遍历接口
    for...of
    for(let x of y){
    }
  • includes() startWith() endWith(), 同事支持第二个参数表示起始位置
  • repeat()
    'x'.repeat(3) // "xxx"
    'hello'.repeat(2) // "hellohello"
    'na'.repeat(0) // ""
  • padStart() padEnd()
    'x'.padStart(5, 'ab') // 'ababx'
    'x'.padStart(4, 'ab') // 'abax'
    'x'.padEnd(5, 'ab') // 'xabab'
    'x'.padEnd(4, 'ab') // 'xaba'
  • 模板字符串 (前后都有一个`)
    foo ${fn()} bar
    大括号中可以是变量,也可以是方法`
  • 可以直接 fn模板字符串, 作为参数不用加小括号。
    alert(123)直接弹出123,而alert123首先123输出是[123]。 如果按照直观理解应该弹出[123],但是alert会将弹出信息进行[123].toString()的隐性操作。所以弹出来的是一样,但是中间经历的环节不一样

数值的扩展

  • Number.isFinite() Number.isNaN()
    Number.isFinite()用来检查一个数值是否为有限的(finite),即不是Infinity。
    Number.isNaN()用来检查一个值是否为NaN。
  • Number.parseInt() Number.parceFloat() Number.isInteger()

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

  • Math.sign()
    它会返回五种值。
    参数为正数,返回+1;
    参数为负数,返回-1;
    参数为 0,返回0;
    参数为-0,返回-0;
    其他值,返回NaN。

函数的扩展

  • 参数默认值是惰性求值的
    let x = 99;
    function foo(p = x + 1) {
    console.log(p);
    }
    foo() // 100
    x = 100;
    foo() //
  • 函数的length属性 返回不是默认值的参数个数
    (function (a) {}).length // 1
    (function (a = 5) {}).length // 0
    (function (a, b, c = 5) {}).length // 2
    上面代码中,length属性的返回值,等于函数的参数个数减去指定了默认值的参数个数.
    如果设置了默认值的参数不是尾参数,那么length属性也不再计入后面的参数了。

  • 在ES5中,arguments对象不是数组,而是一个类似数组的对象。所以为了使用数组的方法,必须使用Array.prototype.slice.call先将其转为数组。ES6中,rest 参数就不存在这个问题,它就是一个真正的数组,数组特有的方法都可以使用。下面是一个利用 rest 参数改写数组push方法的例子。

  • name属性,返回函数名
  • 剪头函数 -> 直接返回对象的话要加上括号
    // 报错
    let getTempItem = id => { id: id, name: "Temp" };
    // 不报错
    let getTempItem = id => ({ id: id, name: "Temp" });

    使用注意点

  • 箭头函数有几个使用注意点。
    (1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象(一般是window)。
    (2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
    (3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
    (4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

  • 尾调用优化 内层函数的调用栈会取代外层函数的调用栈,释放外层函数的变量等。

数组的扩展

  • 扩展运算符(spread)是三个点(…)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
    console.log(...[1, 2, 3])
    // 1 2 3
    console.log(1, ...[2, 3, 4], 5)
    // 1 2 3 4 5
  • 数组的拷贝
    const a1 = [1, 2];
    // 写法一
    const a2 = [...a1];
    // 写法二
    const [...a2] = a1;
  • 合并数组
    const arr1 = ['a', 'b'];
    const arr2 = ['c'];
    const arr3 = ['d', 'e'];
    // ES5 的合并数组
    arr1.concat(arr2, arr3);
    // [ 'a', 'b', 'c', 'd', 'e' ]
    // ES6 的合并数组
    [...arr1, ...arr2, ...arr3]
    // [ 'a', 'b', 'c', 'd', 'e' ] 但是是浅拷贝

对象的扩展

  • 属性的简洁表示法
  • 属性名表达式
    // 方法一
    obj.foo = true;
    // 方法二
    obj['a' + 'bc'] = 123;
  • 方法的 name 属性
    const person = {
    sayName() {
    console.log('hello!');
    },
    };
    person.sayName.name // "sayName"

  • Object.assign 方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target), 只是深拷贝了一层,下层都为浅拷贝。

  • 对象的拷贝
    let z = { a: 3, b: 4 };
    let n = { ...z };
    n // { a: 3, b: 4 }
    let aClone = { ...a };
    // 等同于
    let aClone = Object.assign({}, a);

Symbol

如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是 ES6 引入Symbol的原因。
ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。

Set 和 Map (都实现了Iterrator接口)

  • Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。
    操作方法
    add(value):添加某个值,返回 Set 结构本身。
    delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
    has(value):返回一个布尔值,表示该值是否为Set的成员。
    clear():清除所有成员,没有返回值。
    遍历操作
    Set 结构的实例有四个遍历方法,可以用于遍历成员。
    keys():返回键名的遍历器
    values():返回键值的遍历器
    entries():返回键值对的遍历器
    forEach():使用回调函数遍历每个成员
  • WeakSet
    与set最大区别是WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。

    这是因为垃圾回收机制依赖引用计数,如果一个值的引用次数不为0,垃圾回收机制就不会释放这块内存。结束使用该值之后,有时会忘记取消引用,导致内存无法释放,进而可能会引发内存泄漏。WeakSet 里面的引用,都不计入垃圾回收机制,所以就不存在这个问题。因此,WeakSet 适合临时存放一组对象,以及存放跟对象绑定的信息。只要这些对象在外部消失,它在 WeakSet 里面的引用就会自动消失。

    由于上面这个特点,WeakSet 的成员是不适合引用的,因为它会随时消失。另外,由于 WeakSet 内部有多少个成员,取决于垃圾回收机制有没有运行,运行前后很可能成员个数是不一样的,而垃圾回收机制何时运行是不可预测的,因此 ES6 规定 WeakSet 不可遍历。

    这些特点同样适用于本章后面要介绍的 WeakMap 结构。
  • Map实例的属性和操作方法
    size属性返回 Map 结构的成员总数。
    set(key, value)
    get(key)
    has(key)
    delete(key)
    clear()
  • Map实例的遍历方法与set相同
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值