• ES6 基础知识


    1.let 和 const

    在ES6之前,js只有全局作用域和函数作用域,ES6中let关键字为其引入了块级作用域。 

    //{}代码块
    {
    var a = 5;
    let b = 6;
    }
    console.log(a);     //5
    console.log(b);     //b is undefined
    

    let声明的变量只能在其所在的代码块内才能访问,var声明的变量由于是全局变量,因此可以在代码块外访问 

    const用来定义常量,相当于java中的final关键字。

    并且const声明常量之后就必须立即初始化! 

    2.暂时性死区

    var声明的变量可以在声明之前使用,相当于默认为其声明其值为undefined了; 

    但是,let声明的变量一旦用let声明,那么在声明之前,此变量都是不可用的,术语称为“暂时性死区”。

    console.log(a);                     //undefined
    var a=8;
    console.log("----------");
    console.log(b);                     //控制台报错
    let b=9;
    

    所以我们要养成变量先声明再使用的好习惯。 

    3.解构赋值

    以前,为变量赋值,只能直接指定值。

    let a = 1;
    let b = 2;
    let c = 3;
    

    ES6 允许写成下面这样。可以理解为“模式匹配”。

    let [a, b, c] = [1, 2, 3];
    

    如果解构不成功,变量的值就等于undefined。  

    let [x, y, ...z] = ['a'];
    x // "a"
    y // undefined
    z // []
    

    另一种情况是不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功。  

    let [x, y] = [1, 2, 3];
    x // 1
    y // 2
    
    let [a, [b], d] = [1, [2, 3], 4];
    a // 1
    b // 2
    d // 4
    

    4.字符串的扩展

    //Unicode表示法
    "u{码点}"
    "u{41}u{42}u{43}"                 //"ABC"
    
    let str = "書剑恩仇录";
    str.codePointAt(0).toString(16);    //返回字符的码点并由十进制转到16进制---66f8
    String.fromCodePoint(0x66f8);       //返回码点对应的字符---書
    for (let a of str){
       console.log(a);
    }                                   //for...of循环遍历字符串中每个字符挨个输出字符
    str.at(0);                          //返回指定位置的字符,目前只是提案
    str.startsWith('書',0);             //从指定位置往后开始检查,是否以“書”开始,位置参数可省略,默认为0
    str.endsWith('剑',1);               //从指定位置向前检查,是否以“剑”结束
    str.includes('恩',1);               //同上,不再啰嗦
    str.repeat(2);                      //字符串重复指定次数“書剑恩仇录書剑恩仇录”,小数取整,Infinity和负数报错
    str.padStart(8,'ab');               //指定字符从前开始补直到字符串长度符合要求,"aba書剑恩仇录"
    str.padEnd(8,'ab');                 //指定字符从后开始补直到字符串长度符合要求,"書剑恩仇录aba",若长度小于原长度,返回原字符串,上同
    
    模板字符串

    模板字符串采用反引号 ` 标识,并且模板字符串中的空格、换行将在输出时有所保留。
    传统的 JavaScript 语言,输出模板通常是这样写的。

    $('#result').append(
      'There are <b>' + basket.count + '</b> ' +
      'items in your basket, ' +
      '<em>' + basket.onSale +
      '</em> are on sale!'
    );
    

    上面这种写法相当繁琐不方便,ES6 引入了模板字符串解决这个问题。  

    $('#result').append(`
      There are <b>${basket.count}</b> items
       in your basket, <em>${basket.onSale}</em>
      are on sale!
    `);
    
    // 普通字符串
    `In JavaScript '
    ' is a line-feed.`
    
    // 多行字符串
    `In JavaScript this is
     not legal.`
    
    console.log(`string text line 1 
    string text line 2`);
    
    // 字符串中嵌入变量
    let name = "Bob", time = "today";
    `Hello ${name}, how are you ${time}?`
    

    5.正则的扩展

    RegExp 构造函数

    在 ES5 中,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覆盖。

    6.数值的扩展

    //从 ES5 开始,在严格模式之中,八进制就不再允许使用前缀0表示,ES6 进一步明确,要使用前缀0o表示。
    //如果要将0b和0o前缀的字符串数值转为十进制,要使用Number方法。
    Number('0b111')  // 7
    Number('0o10')  // 8
    
    
    //Number.isFinite()用来检查一个数值是否为有限的(finite),即不是Infinity。
    Number.isFinite(0.1); // true
    Number.isFinite(NaN); // false
    Number.isFinite(Infinity); // false
    Number.isFinite('0.1'); // false
    Number.isFinite(true); // false
    //传统方法会先调用Number()将非数值的值转为数值,再进行判断,而这两个新方法只对数值有效
    isFinite("25") // true
    Number.isFinite("25") // false
    
    
    //Number.isNaN()用来检查一个值是否为NaN。
    Number.isNaN(NaN) // true
    Number.isNaN(15) // false
    Number.isNaN('15') // false
    Number.isNaN(true) // false
    Number.isNaN(9/NaN) // true
    Number.isNaN('true' / 0) // true
    Number.isNaN('true' / 'true') // true
    //传统方法会先调用Number()将非数值的值转为数值,再进行判断,而这两个新方法只对数值有效
    isNaN("NaN") // true
    Number.isNaN("NaN") // false
    
    
    //ES6 将全局方法parseInt()和parseFloat(),移植到Number对象上面,行为完全保持不变。
    // ES5的写法
    parseInt('12.34') // 12
    parseFloat('123.45#') // 123.45
    // ES6的写法
    Number.parseInt('12.34') // 12
    Number.parseFloat('123.45#') // 123.45
    
    //Number.isInteger()用来判断一个数值是否为整数。
    Number.isInteger(25) // true
    Number.isInteger(25.0) // true
    Number.isInteger(25.1) // false
    Number.isInteger() // false
    Number.isInteger(null) // false
    Number.isInteger('15') // false
    Number.isInteger(true) // false
    
    //ES6 在Number对象上面,新增一个极小的常量Number.EPSILON。根据规格,它表示 1 与大于 1 的最小浮点数之间的差。
    Number.EPSILON === Math.pow(2, -52) // true
    Number.EPSILON // 2.220446049250313e-16
    Number.EPSILON.toFixed(20) // "0.00000000000000022204"
    
    //ES6 引入了Number.MAX_SAFE_INTEGER和Number.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
    
    //ES6 在 Math 对象上新增了 17 个与数学相关的方法。所有这些方法都是静态方法,只能在 Math 对象上调用。
    Math.trunc(4.1) // 4    Math.trunc方法用于去除一个数的小数部分,返回整数部分。
    Math.sign(-5) // -1     Math.sign方法用来判断一个数到底是正数、负数、还是零
    Math.cbrt('8') // 2     Math.cbrt方法用于计算一个数的立方根。
    //........
    

    7.函数的扩展

    参数默认值

    ES5中的写法
    function log(x, y) {
      //y = y || 'World';  --> 这种写法如果y是false则不起作用,所以用下面的方式复制
      if (typeof y === 'undefined') {
        y = 'World';
      }
      console.log(x, y);
    }
    
    log('Hello') // Hello World
    
    ES6中的写法
    function log(x, y = 'World') {
      console.log(x, y);
    }
    log('Hello') // Hello World
    

    与解构赋值默认值的结合

    function m1({x = 0, y = 0} = {}) {
      return [x, y];
    }
    

    作用域

    let x = 1;
    
    function f(y = x) {
      let x = 2;
      console.log(y);
    }
    
    f() // 1
    

    参数y的默认值等于变量x。调用函数f时,参数形成一个单独的作用域。在这个作用域里面,默认值变量x指向第一个参数x,而不是全局变量x,所以输出是2。

    name属性

    function foo() {}
    foo.name // "foo"
    

    箭头函数

    var f = v => v;
    // 等同于
    var f = function (v) {
      return v;
    };
    
    //如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。
    var f = () => 5;
    // 等同于
    var f = function () { return 5 };
    

    8.数组的扩展

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

    //----------------------------复制数组
    // ES5的 写法
    const a1 = [1, 2];
    const a2 = a1.concat();
    a2[0] = 2;
    a1 // [1, 2]
    // ES6的 写法
    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' ]
    

    Array.from方法用于将两类对象转为真正的数组

    Array.from([1, 2, 3])// [1, 2, 3]
    

    Array.of方法用于将一组值,转换为数组。

    Array.of(3, 11, 8) // [3,11,8]
    

    数组实例的copyWithin方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。也就是说,使用这个方法,会修改当前数组。  

    //Array.prototype.copyWithin(target, start = 0, end = this.length)
    [1, 2, 3, 4, 5].copyWithin(0, 3)
    // [4, 5, 3, 4, 5]  --> 上面代码表示将从 3 号位直到数组结束的成员(4 和 5),复制到从 0 号位开始的位置,结果覆盖了原来的 1 和 2。
    

    数组实例的find方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined。

    [1, 4, -5, 10].find((n) => n < 0)
    // -5
    
    [1, 5, 10, 15].find(function(value, index, arr) {
      return value > 9;
    }) // 10
    

    数组实例的findIndex方法的用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。

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

    fill方法使用给定值,填充一个数组。

    ['a', 'b', 'c'].fill(7)
    // [7, 7, 7]
    
    new Array(3).fill(7)
    // [7, 7, 7]
    

    entries(),keys()和values()——用于遍历数组

    for (let index of ['a', 'b'].keys()) {
      console.log(index);
    }
    // 0
    // 1
    
    for (let elem of ['a', 'b'].values()) {
      console.log(elem);
    }
    // 'a'
    // 'b'
    
    for (let [index, elem] of ['a', 'b'].entries()) {
      console.log(index, elem);
    }
    // 0 "a"
    // 1 "b"
    
    //如果不使用for...of循环,可以手动调用遍历器对象的next方法,进行遍历。
    let letter = ['a', 'b', 'c'];
    let entries = letter.entries();
    console.log(entries.next().value); // [0, 'a']
    console.log(entries.next().value); // [1, 'b']
    console.log(entries.next().value); // [2, 'c']
    

    includes方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似

    [1, 2, 3].includes(2)     // true
    [1, 2, 3].includes(4)     // false
    [1, 2, NaN].includes(NaN) // true
    

    数组的空位指,数组的某一个位置没有任何值。比如,Array构造函数返回的数组都是空位。

    Array(3) // [, , ,]
    
    0 in [undefined, undefined, undefined] // true
    0 in [, , ,] // false
    

    9.对象的扩展

    //ES6 允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
    function f(x, y) {
      return {x, y};
    }
    // 等同于
    function f(x, y) {
      return {x: x, y: y};
    }
    f(1, 2) // Object {x: 1, y: 2}
    
    //JavaScript 定义对象的属性,有两种方法。
    // 方法一
    obj.foo = true;
    
    // 方法二
    obj['a' + 'bc'] = 123;
    
    var obj = {
      foo: true,
      abc: 123
    };
    

    10.Symbol

    ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。

    let s = Symbol();
    
    typeof s
    // "symbol"
    

    上面代码中,变量s就是一个独一无二的值。typeof运算符的结果,表明变量s是 Symbol 数据类型,而不是字符串之类的其他类型。

    11.Set和Map 

    ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

    const s = new Set();
    
    [2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));
    
    for (let i of s) {
      console.log(i);
    }
    // 2 3 5 4
    

    ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。

    const m = new Map();
    const o = {p: 'Hello World'};
    
    m.set(o, 'content')
    m.get(o) // "content"
    
    m.has(o) // true
    m.delete(o) // true
    m.has(o) // false
    

    12.Proxy与Reflect


    Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程

    实例:使用 Proxy 实现观察者模式
    观察者模式(Observer mode)指的是函数自动观察数据对象,一旦对象有变化,函数就会自动执行。

    const person = observable({
      name: '张三',
      age: 20
    });
    
    function print() {
      console.log(`${person.name}, ${person.age}`)
    }
    
    observe(print);
    person.name = '李四';
    // 输出
    // 李四, 20
    

    13.Promise

    Promise 是异步编程的一种解决方案,比传统的解决方案–回调函数和事件--更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了语法,原生提供了Promise

    所谓Promise ,简单说就是一个容器,里面保存着某个未来才回结束的事件(通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。
    Promise 对象的状态不受外界影响

    三种状态:

    pending:进行中
    fulfilled : 已经成功
    rejected :已经失败
    ajax的异步:

    $(function(){
        $('#send').click(function(){
             $.ajax({
                 type: "GET",
                 url: "test.json",
                 data: {username:$("#username").val(), content:$("#content").val()},
                 dataType: "json",
                 success: function(data){
                             $('#resText').empty();   //清空resText里面的所有内容
                             var html = ''; 
                             $.each(data, function(commentIndex, comment){
                                   html += '<div class="comment"><h6>' + comment['username']
                                             + ':</h6><p class="para"' + comment['content']
                                             + '</p></div>';
                             });
                             $('#resText').html(html);
                          }
             });
        });
    });
    

    上面的例子实现了一个类似于表单提交的功能。
    Promise的异步:

    let promise = new Promise(function(resolve, reject) {
      console.log('Promise');                        //实例化后立即执行
      resolve();                                     //任务(成功)完成
    });
    
    promise.then(function() {
      console.log('resolved.');                      //任务结束执行
    });
    
    console.log('Hi!');                              //在实例化promise的同时,执行
    

    14.Iterator接口

    for...in循环:只能获取对象的键名
    for...of循环:可以获得键值,只返回具有数字索引的属性(键或值)
    
    var arr = ['a', 'b', 'c', 'd'];
    for (let a in arr) {
      console.log(a);                  // 0 1 2 3
    }
    for (let a of arr) {
      console.log(a);                  // a b c d
    }
    

    15.async函数

    async就表示asynchronous(异步的),async函数会返回一个Promise对象,自然能够调用其方法:
    promise.then(success()).catch(error()).finally(function(){});

    async function getStockPriceByName(name) {
        const symbol = await getStockSymbol(name);
        const stockPrice = await getStockPrice(symbol);
        return stockPrice;             //stockPrice是一个promise对象
    }
    
    getStockPriceByName('goog').then(function (result) {
        console.log(result);
    });
    

    16.class

    class ColorPoint extends Point {
      constructor(x, y, color) {
        super(x, y);                                // 调用父类的constructor(x, y)
        this.color = color;
      }
    
      toString() {
        return this.color + ' ' + super.toString(); // 调用父类的toString()
      }
    }
    

    17.模块化

    //lib.js
    var counter = 3;
    function incCounter() {
      counter++;
    }
    module.exports = {
      counter: counter,
      incCounter: incCounter,
    };
    

    这是一个js模块,对外暴露两个属性counter(变量)、incCounter(函数),然后再去加载这个模块
    这样就可以去调用该模块对外暴露的属性了:

    // main.js
    var mod = require('./lib');
    
    console.log(mod.counter);  // 3
    mod.incCounter();
    console.log(mod.counter);  // 3
    

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

  • 相关阅读:
    sun.misc.Unsafe
    一个普通Java程序包含哪些线程??
    类加载-类加载器
    类加载-类的生命周期
    类加载-初始化的触发
    Java语法糖
    Java线程池
    Java线程池之ThreadPoolExecutor
    【结构型】- 适配器模式
    数据结构与算法之排序(3)插入排序 ——in dart
  • 原文地址:https://www.cnblogs.com/lgx5/p/11072022.html
Copyright © 2020-2023  润新知