Es6学习

作者: 狐尼克朱迪 | 来源:发表于2016-08-15 14:56 被阅读0次

    简单做个笔记,供自己以后查阅。

    1. let和const

    块级作用域:

    Es5的时候只存在两者作用域:全局作用域和函数作用域,Es6引入块级作用域。

      function f1() {
      let n = 5;
      if (true) {
        let n = 10;
      }
      console.log(n); // 5
    }
    
    let

    局域化的var,仅在块级作用域内有效,存在以下特性:

    1. 不存在变量名提升
    2. 暂时性死区:作用域内存在let,那么let声明的变量不会受外部影响。这么设计主要是为了避免使用在前,声明在后的不良习惯。 先声明后使用,扔掉那个所谓的变量名提升了吧..
      var bb=2;
    if(true){
         console.log(aa);
         console.log(bb); // ReferenceError: bb is not defined
         var aa=1;
         let bb; 
    }
    
    1. 不能重复声明一个变量:
    var aa=1;
    let aa=1; // "SyntaxError: Identifier 'aa' has already been declared
    let aa=1; // 同上
    
    const

    声明常量,字面常量的话不改进行赋值修改;对象字面常量的话,可以修改其内部元素的值。

    const aa=1;
    aa=2; // TypeError: Assignment to constant variable.
    const cc=[];
    cc[0] =1;
    cc[1] =2;
    console.log(cc);
    cc = [1,2,3]; // TypeError: Assignment to constant variable.
    

    2. 解构赋值

    如下面的例子:

      let [x, , y] = [1, 2, 3];  // x:1  y:3
      let [x = 1, y = x] = [2];  // x=2; y=2
      var {x, y = 5} = {x: 1};  // x:1  y:5  设置默认值
      var {x, y = 5} = {x: 1, y: undefined};  // x:1  y:5  undefined不影响默认值
      var {x, y = 5} = {x: 1, y: null};  // x:1  y:null  
      var {a, b} = {b:1, a:1}; console.log(a); // a:1  b:1
      const [a, b, c, d, e] = 'hello';  // a:'h' ... e:'o' 
    

    最基本的作用是交换变量的值: [x, y] = [y, x];,可以由此进行衍生。

    3. 字符串扩展

    JavaScript允许采用\uxxxx形式表示一个字符,其中“xxxx”表示字符的码点。
    Es6中提供了两个string和unicode互转函数:codePointAt ()和String.fromCharCode(),相对于Es5中存在的两个函数:charCodeAt()和String.fromCharCode(),功能有些区别:

       var s = "𠮷";
      s.length // 2
      s.charAt(0) // ''
      s.charAt(1) // ''
      s.charCodeAt(0) // 55362
      s.charCodeAt(1) // 57271
    

    字符和unicode的互相转换方法:

      var str2Unicode = function(str){
        return "\\u" + ("00" + str.charCodeAt(0).toString(16)).slice(-4)
      }
      var unicode2Str = function(str){
          return unescape(str);
      }
    

    以下是表示"z"的几种方法:

      '\z' === 'z'  // true
    '\172' === 'z' // true
    '\x7A' === 'z' // true
    '\u007A' === 'z' // true
    '\u{7A}' === 'z' // true Es6中引入
    

    JavaScript内部,字符以UTF-16的格式储存,每个字符固定为2个字节。对于那些需要4个字节储存的字符(Unicode码点大于0xFFFF的字符),JavaScript会认为它们是两个字符。
    Es6中引入了几个处理字符串的函数: includes(), startsWith(), endsWith() , repeat(), padStart(),padEnd()
    Es6中引入的``可以包含含有换行符的字符串,这样可以很方便的早console中处理字符串,这个也极大的方便了前端模板的处理。

    重音符`的应用.png

    前端模板示例:

      var x = 1;
      var y = 2;
      console.log(`${x} + ${y} = ${x + y}`)    //  1 + 2 = 3
    

    4. 正则扩展

    引入了u修饰符,用来正确处理大于\uFFFF的Unicode字符。

      /^\uD83D/u.test('\uD83D\uDC2A')    //   false
      /^\uD83D/.test('\uD83D\uDC2A')    //   true
    

    上面代码中,\uD83D\uDC2A是一个四个字节的UTF-16编码,代表一个字符。但是,ES5不支持四个字节的UTF-16编码,会将其识别为两个字符,导致第二行代码结果为true。加了u修饰符以后,ES6就会识别其为一个字符,所以第一行代码结果为false。

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

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

    5. 数字扩展

    增加了几个数字处理函数:

      Number.isFinite(), 
      Number.isNaN(), 
      Number.parseInt(), 
      Number.parseFloat(), 
      Number.isInteger(), 
      Number.EPSILON   //极小值
      Number.isSafeInteger()  // -2^53到2^53之间
      
      Math.trunc()  // 去除一个数的小数部分,返回整数部分。
      Math.sign()    // 判断正负
      Math.cbrt()     // 求立方根
    

    6. 数组扩展

    提供了一下新的函数:

        Arrary.from    // [].slice类似
        Array.of()       // 转成数组
        copyWithin(target, start = 0, end = this.length)    // target(必需):从该位置开始替换数据。start(可选):从该位置开始读取数据,默认为0。如果为负值,表示倒数。end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
        find()和findIndex()  // 查找数据
        fill()    // 填充数组
        includes()    // 判断是否包含
    

    7. 函数扩展

    函数参数的默认值:

      function foo(a, b=2){ console.log(a, b);}
    

    函数作用域:

    // 1. y()执行影响的是形参x,而且内部对x进行重新声明,因此对别的数值没什么影响。
    var x = 1;
    function foo(x, y = function() { x = 2; }) {
      var x = 3;
      y();
      console.log(x);
    }
     foo();   //  3
     console.log(x); // 1
    
    // 2. y()只是影响了形参x
    var x = 1;
    function foo(x, y = function() { x = 2; }) {
      x = 3;
      y();
      console.log(x);
    }
    foo();  // 2
    console.log(x);  //  1
    
    // 3.  形参y管理的作用域是外部 因此会把外面的x的1改为2
    var x = 1;
    function foo(y = function() { x = 2; }) {
      var x = 3;
      y();
      console.log(x);
    }
    foo(); // 3
    console.log(x); // 2
    

    扩展运算符... 将一个数组转为用逗号分隔的参数序列。如:

      console.log(1, ...[2, 3, 4], 5)  // 1 2 3 4 5
      // 合并数组
      [1, 2].concat(more)  // ES5
      [1, 2, ...more]  // ES6
      // 解构赋值
      const [first, ...rest] = [1, 2, 3, 4, 5];
      first // 1
      rest  // [2, 3, 4, 5]
      // 字符串
      [...'hello']    // [ "h", "e", "l", "l", "o" ]
      // 实现了Iterator接口的对象  
      let map = new Map([
        [1, 'one'],
        [2, 'two'],
        [3, 'three'],
      ]);
      let arr = [...map.keys()]; // [1, 2, 3]
    

    箭头函数本身没有this和arguments,只能引用外层的this:

    function foo() {
      return () => {
        return () => {
          return () => {
            console.log('id:', this.id);
          };
        };
      };
    }
    var f = foo.call({id: 1});
    var t1 = f.call({id: 2})()(); // id: 1
    var t2 = f().call({id: 3})(); // id: 1
    var t3 = f()().call({id: 4}); // id: 1
    
    // arguments
    function foo() {
      setTimeout(() => {
        console.log('args:', arguments);
      }, 100);
    }
    
    foo(2, 4, 6, 8)
    // args: [2, 4, 6, 8]
    

    由于箭头函数没有自己的this,所以当然也就不能用call()、apply()、bind()这些方法去改变this的指向

    (function() {
      return [
        (() => this.x).bind({ x: 'inner' })()
      ];
    }).call({ x: 'outer' });   // ['outer']
    

    8. 对象扩展

    引入了一下几个函数:

      Object.is()   // 判断两个值是否相等 和===类似
      // 区别
      +0 === -0 //true
      NaN === NaN // false
      Object.is(+0, -0) // false  
      Object.is(NaN, NaN) // true
    
      Object.assign()   // 合并对象
      // 潜copy
      var obj1 = {a: {b: 1}};
      var obj2 = Object.assign({}, obj1);
      obj1.a.b = 2;
      obj2.a.b // 2
      // 属性是替换 而不是覆盖
      var target = { a: { b: 'c', d: 'e' } }
      var source = { a: { b: 'hello' } }
      Object.assign(target, source) // { a: { b: 'hello' } }
    
      Object.getOwnPropertyDescriptor    // 属性的描述对象
      // for...in循环、Object.keys()、JSON.stringify()、Object.assign()均会忽略enumerable为false的属性
    
      Object.keys()、Object.values() 、Object.entries()  // 获取key、value和键值对
    

    9. Symbol

    Undefined、Null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)之外的第七种类型。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

      // 可以显示转换成别的类型
      var sym = Symbol('My symbol');String(sym)   // 'Symbol(My symbol)'
      sym.toString()   // 'Symbol(My symbol)'
    
      // Symbol值不能与其他类型的值进行运算,会报错。
      var sym = Symbol('My symbol');
      "your symbol is " + symbol    // TypeError
    

    Symbol作为属性名,该属性不会出现在for...in、for...of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()返回。可通过Object.getOwnPropertySymbols返回。

    10. Proxy和Reflect

    Proxy可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。

     var obj = new Proxy({}, {
      get: function (target, key, receiver) {
        console.log(`getting ${key}!`);
        return Reflect.get(target, key, receiver);
      },
      set: function (target, key, value, receiver) {
        console.log(`setting ${key}!`);
        return Reflect.set(target, key, value, receiver);
      }
    });
    
    obj.count = 1       //  setting count!
    ++obj.count         //  getting count!  setting count!  2
    

    Reflect:将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上;或者修改某些Object方法的返回结果,让其变得更合理。

    11. Set和Map

    • Set:类似于数组,但是没有重复的值
    var set = new Set([1, 2, 3, 4, 4]);  [...set]  // 1 2 3 4
    

    属性: size
    操作方法: add、delete、has、clear
    遍历方法:keys()、values()、entries()、forEach()

    • Map:类似于对象,是键值对的集合,但是键值不限于字符串
    var m = new Map();
    var o = {p: "Hello World"};
    m.set(o, "content")
    m.get(o) // "content"
    

    属性、操作方法和遍历方法与Set类似

    12. Class

    Class和function相似:

    // function
    function Point(x, y) {
      this.x = x;
      this.y = y;
    }
    Point.prototype.toString = function () { ... };
    
    // class
    class Point {
      constructor(x, y) {
        this.x = x;
        this.y = y;
      }
      toString() { ... }
    }
    

    区别:

    • Class中的方法是不可枚举的(enumerable:false),而function就是可以的。

    借用Symbol实现私有方法:

    class foo({
      // 共有方法
      foo (baz) {
        this[bar](baz);
      }
      // 私有方法
      [bar](baz) {
        return this[snaf] = baz;
      }
    });
    

    静态方法:

    class Foo {
      static classMethod() {
        return 'hello';
      }
    }
    Foo.classMethod()
    

    静态属性:

     // 1.2 两种写法都无效(Es6)
    class Foo {
      // 1
      prop: 2
      // 2
      static prop: 2
    }
    // 有效
    Foo.prop = 1;
    

    new.target: 非new操作时为undefined,否则为类构造函数

    function Person(name) {
      if (new.target !== undefined) {
        this.name = name;
      } else {
        throw new Error('必须使用new生成实例');
      }
    }
    

    相关文章

      网友评论

          本文标题:Es6学习

          本文链接:https://www.haomeiwen.com/subject/bxwcdttx.html