• ES6之常用开发知识点:入门(一)


    ES6介绍

    ES6, 全称 ECMAScript 6.0 ,2015.06 发版。

    let 和 const命令

    let命令

    let 命令,用来声明变量。它的用法类似于var,区别在于var声明的变量全局有效,let 声明的变量只在它所在的代码块内有效。

    使用var声明:

    var a = [];
    for (var i = 0; i < 10; i++) {
      a[i] = function () {
        console.log(i);
      };
    }
    a[6](); // 10

    使用闭包解决:

    var a = [];
    for (var i = 0; i < 10; i++) {
        (function(i){
            a[i] = function () {
              console.log(i);
            };
        })(i); 
    }
    a[6](); // 6

    使用let:

    var a = [];
    for (let i = 0; i < 10; i++) {
      a[i] = function () {
        console.log(i);
      };
    }
    a[6](); // 6
    • let 不存在变量提升,必须先声明后使用,否则报错;var存在变量提升,未声明前使用输出 undefined。
    • let 存在暂时性死区,在代码块内,使用let命令声明变量之前,该变量都是不可用的。
    • let 不允许重复声明。

    const 命令

    const 声明一个只读的常量。一旦声明,常量的值就不能改变。不能只声明不赋值。

    const a = 10;
    a = 20; // 报错
    
    const b; // 报错

    const 的作用域与 let 相同。

    if(true) {
      const num = 5;
    }
    console.log(num); // 报错

    const 声明对象,常量对象内存地址,因此对象本身可改,但是给常量重新赋值就会报错。

    const obj = {};
    obj.a = 'a';
    
    obj = {}; // 报错

    块级作用域和函数作用域

    ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。

    第一种场景,内层变量可能会覆盖外层变量。

    var tmp = new Date();
    
    function f() {
      console.log(tmp);
      if (false) {
        var tmp = 'hello world';
      }
    }
    
    f(); // undefined

    第二种场景,用来计数的循环变量泄露为全局变量。

    var s = 'hello';
    
    for (var i = 0; i < s.length; i++) {
      console.log(s[i]);
    }
    
    console.log(i); // 5

    ES6的块级作用域

    let实际上为 JavaScript 新增了块级作用域。

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

    块级作用域的出现,实际上使得获得广泛应用的匿名立即执行函数表达式(匿名 IIFE)不再必要了。

    // IIFE 写法
    (function () {
      var tmp = ...;
      ...
    }());
    
    // 块级作用域写法
    {
      let tmp = ...;
      ...
    }

    ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。

    // 情况一
    if (true) {
      function f() {}
    }
    
    // 情况二
    try {
      function f() {}
    } catch(e) {
      // ...
    }

    上面两种函数声明,根据 ES5 的规定都是非法的。

    ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。

    function f() { console.log('I am outside!'); }
    
    (function () {
      if (false) {
        // 重复声明一次函数f
        function f() { console.log('I am inside!'); }
      }
    
      f();
    }());

    上面代码在 ES5 中运行,会得到“I am inside!”,因为在if内声明的函数f会被提升到函数头部,实际运行的代码如下。

    // ES5 环境
    function f() { console.log('I am outside!'); }
    
    (function () {
      function f() { console.log('I am inside!'); }
      if (false) {
      }
      f();
    }());

    ES6 就完全不一样了,理论上会得到“I am outside!”。因为块级作用域内声明的函数类似于let,对作用域之外没有影响。但是,如果你真的在 ES6 浏览器中运行一下上面的代码,是会报错的,这是为什么呢?

    // 浏览器的 ES6 环境
    function f() { console.log('I am outside!'); }
    
    (function () {
      if (false) {
        // 重复声明一次函数f
        function f() { console.log('I am inside!'); }
      }
    
      f();
    }());
    // Uncaught TypeError: f is not a function

    上面的代码在 ES6 浏览器中,都会报错。

    原来,如果改变了块级作用域内声明的函数的处理规则,显然会对老代码产生很大影响。为了减轻因此产生的不兼容问题,浏览器的实现可以不遵守上面的规定,有自己的行为方式。

    • 允许在块级作用域内声明函数。
    • 函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
    • 同时,函数声明还会提升到所在的块级作用域的头部。

    注意,上面三条规则只对 ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作let处理。

    根据这三条规则,浏览器的 ES6 环境中,块级作用域内声明的函数,行为类似于var声明的变量。上面的例子实际运行的代码如下。

    // 浏览器的 ES6 环境
    function f() { console.log('I am outside!'); }
    (function () {
      var f = undefined;
      if (false) {
        function f() { console.log('I am inside!'); }
      }
    
      f();
    }());
    // Uncaught TypeError: f is not a function

    考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。

    另外,还有一个需要注意的地方。ES6的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。

    // 第一种写法,报错
    if (true) let x = 1;
    
    // 第二种写法,不报错
    if (true) {
      let x = 1;
    }

    上面代码中,第一种写法没有大括号,所以不存在块级作用域,而let只能出现在当前作用域的顶层,所以报错。第二种写法有大括号,所以块级作用域成立。

    函数声明也是如此,严格模式下,函数只能声明在当前作用域的顶层。

    // 不报错
    if (true) {
      function f() {}
    }
    
    // 报错
    'use strict';
    if (true)
      function f() {}

    变量的解构赋值

    ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

    数组的解构赋值

    模式匹配赋值,如果解构不成功,变量的值就等于 undefined。

    let [a, [[b], c]] = [1, [[2], 3]];
    console.log(a,b,c); // 1, 2, 3
    
    let [x, , y, z] = [1, 2, 3];
    console.log(x); // 1
    console.log(y); // 3
    console.log(z); // undefined

    不完全解构赋值,等号左边的模式,只匹配一部分的等号右边的数组。

    let [x, [y], z] = [1, [2, 3], 4];
    console.log(x); // 1
    console.log(y); // 2
    console.log(z); // 4

    数组结构赋值右边必须是数组,模式不匹配则报错。

    let [a] = {}; // 报错

    解构赋值可以添加默认值,并且可以引用解构赋值的其他变量。

    let [a = 1, b = 2] = [, 3];
    console.log(a); // 1
    console.log(b); // 3
    
    let [x = 1, y = x] = [];  // x = 1; y = 1
    let [x = 1, y = x] = [2]; // x = 2; y = 2

    数组解构赋值可用于交换变量的值。

    let [a, b] = [1, 2];
    console.log(a, b); // 1, 2
    [b, a] = [a, b];
    console.log(a, b); // 2, 1

    对象的解构赋值

    变量必须与属性同名

    let { a, b, c } = { a: 'aaa', b: 'bbb' };
    console.log(a); // 'aaa'
    console.log(b); // 'bbb'
    console.log(c); // undefined

    变量名与属性名不一致

    let { a: x, b: y } = { a: 'aaa', b: 'bbb' };
    console.log(x); // 'aaa'
    console.log(y); // 'bbb'

    嵌套赋值,如果子对象所在的父属性不存在,会报错,慎用。

    let { a, a: {x}, b: y } = { a: {x: 'xxx',y: 'yyy'}, b: "bbb" };
    console.log(a); // { x: 'xxx', y: 'yyy' }
    console.log(x); // 'xxx'
    
    let {c: {d: {e}}} = {c: 'ccc'}; // 报错
    console.log(e)

    字符串解构赋值

    字符串解构赋值,将字符串转化成数组对象

    const [a,b,c] = '123456789';
    const {length} = '123456789';
    console.log(a, b, c, length); // 1, 2, 3, 9

    类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。

    let {length : len} = 'hello';
    len // 5

    函数参数解构赋值

    function add([x, y]){
      return x + y;
    }
    
    add([1, 2]); // 3

    下面是另一个例子:

    const arr = [[1, 2], [3, 4]].map(([a, b]) => a + b);
    console.log(arr); // [ 3, 7 ]

    函数参数的解构也可以使用默认值。

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

    上面代码中,函数move的参数是一个对象,通过对这个对象进行解构,得到变量x和y的值。如果解构失败,x和y等于默认值。

    注意,下面的写法会得到不一样的结果。

    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]

    上面代码是为函数move的参数指定默认值,而不是为变量x和y指定默认值,所以会得到与前一种写法不同的结果。

    字符串扩展

    for...of 遍历字符串

    for(let codePoint of 'string'){
      console.log(codePoint)
    }
    // 's'
    // 't'
    // 'r'
    // 'i'
    // 'n'
    // 'g'

    includes(),startsWith(),endsWith()

    let s = 'Hello world!';
    
    const [a, b, c] = [
        s.startsWith('Hello', 2),
        s.endsWith('!'),
        s.includes('o w')
    ];
    
    console.log(a, b, c); // false true true

    repeat()

    repeat 方法返回一个新字符串,表示将原字符串重复 n 次。

    • 参数为[-Infinity,-1]或者 Infinity,会报错;
    • 参数为(-1,1)时,相当于参数为 0;
    • 参数为小数时向下取整;
    • 参数 NaN 等同于 0;
    • 参数是字符串,则会先转换成数字。
    'str'.repeat('3') // 'strstrstr'

    padStart(), padEnd()

    padStart(),padEnd()有两个参数,第一个参数为字符串补全生效的最大长度,第二个参数为补全的字符串。

    第二个参数默认为空格,省略第二个参数时默认用空格补全。

    第一个参数小于字符串原长度时,返回原字符串。

    如果用来补全的字符串与原字符串,两者的长度之和超过了最大长度,则会截去超出位数的补全字符串。

    常见用途:补全指定位数,提示字符串格式。

    '123456'.padStart(10, '0') // "0000123456"
    '09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12"

    模版字符串(``)

    const str = 'world';
    const template = `Hello ${str}`;
    console.log(template); // Hello world

    数值扩展

    二进制、八进制表示法

    使用二进制表示法,前缀为 0b,使用八进制表示法,前缀为 0o,ES6 不支持使用 00 前缀表示八进制。

    进制转换使用 toString 方法,使用 Number 方法直接转十进制。

    0b1100100 === 100; // true
    0o144 === 100; // true
    
    (0b1100100).toString(8); // 144
    (0b1100100).toString(10); // 100
    Number('0b1100100'); // 100

    Number.isFinite(),Number.isNaN()

    Number.isFinite()用来检查一个数值是否为有限的(finite),即不是 Infinity。参数类型不是数值,Number.isFinite 一律返回 false。

    Number.isNaN()用来检查一个值是否为 NaN。参数类型不是 NaN,Number.isNaN 一律返回 false。

    Number.isFinite(15); // true
    Number.isFinite(-Infinity); // false
    
    Number.isNaN(15) // false
    Number.isNaN(9/0) // true

    Number.parseInt(), Number.parseFloat()

    ES6 将全局方法 parseInt()和parseFloat(),移植到Number对象上面,行为完全保持不变。

    Number.isInteger()

    Number.isInteger()用来判断一个数值是否为整数。

    Number.isInteger(25) // true
    Number.isInteger(25.0) // true
    Number.isInteger(25.1) // false
    • Number.EPSILON 极小常量,浮点数误差小于这个值可以认为不存在误差;
    • Number.MAX_SAFE_INTEGER 安全整数的最大范围;
    • Number.MIN_SAFE_INTEGER 安全整数的最小范围;
    • Number.isSafeInteger() 用来判断一个整数是否落在安全整数范围之内。
    Number.isSafeInteger(9007199254740993) // false
    Number.isSafeInteger(990) // true
    Number.isSafeInteger(9007199254740993 - 990) // true

    Math 对象的扩展

    Math.trunc() 除去一个数的小数部分,返回整数部分。参数不是数值,内部会先调用 Number()专为数值,对于空值和无法截取整数的值,返回 NaN。(Math 对象的扩展的方法对于非数值的处理方法都一样)

    Math.trunc(5.9) // 5
    Math.trunc(-4.9) // -4
    Math.trunc(null) // 0
    Math.trunc('foo'); // NaN

    Math.sign() 判断一个数是正数、负数、还是零。

    Math.sign(-5) // -1 负数
    Math.sign(5) // +1 正数
    Math.sign(0) // +0 零
    Math.sign(-0) // -0 零
    Math.sign(NaN) // NaN

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

    Math.cbrt(2)  // 1.2599210498948734
    
    // Math.sqrt(x) 计算平方根
    Math.sqrt(2) // 1.4142135623730951
    
    // 幂运算 Math.pow(x,y)
    Math.pow(2, 3)

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

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

    函数扩展

    rest 参数

    ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数,rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。只能是最后一个参数,函数的 length 属性,不包括 rest 参数。

    function sum1(x, y, ...args) {
        let sum = 0;
    
        for (let arg of args) {
            sum += arg;
        }
    
        return sum;
    }
    
    console.log(sum1(1, 2, 3, 4)) // 7
    
    function sum2(...args) {
        return args.reduce((prev, curr) => {
            return prev + curr
        }, 0)
    }
    
    console.log(sum2(1, 2, 3)); // 6

    name 属性

    函数的 name 属性,返回该函数的函数名。对于匿名函数,ES5 返回' ',ES6 返回变量名; Function 构造函数返回的函数实例,name 属性的值为 anonymous;bind 返回的函数,name 属性值会加上 bound 前缀。

    function fn() {}
    fn.name // 'fn'
    
    function foo() {};
    foo.bind({}).name // 'bound foo'
    
    (new Function).name // "anonymous"
    
    (function(){}).bind({}).name // 'bound '

    箭头函数

    const fn = v => v;
    
    // 等同于
    const fn = function (v) {
      return v;
    };

    注意要点

    • 函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象;
    • 不可以当作构造函数,即不可以使用 new 命令,否则会抛出一个错误;
    • 不可以使用 arguments 对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替;
    • 不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数。

    数组扩展

    扩展运算符

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

    const arr = [1, 2, 3];
    arr.push(...[4, 5, 6]);

    扩展运算符的应用:

    • 数组展开
    const arr = [1, 2, 3];
    ...arr // 1, 2, 3
    • 复制数组
    const a1 = [1, 2];
    // 写法一
    const a2 = [...a1];
    // 写法二
    const [...a2] = a1;
    
    // 相当于
    const a1 = [1, 2];
    const a2 = a1.concat();
    • 解构赋值,字符串转数组
    const list = [1, 2, 3];
    [a, ...b] = list;
    console.log(a) // 1
    console.log(b) // [2, 3]
    
    [...'hello'] // ['h', 'e', 'l', 'l', 'o']

    Array.from()

    Array.from 方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)。

    常见的类似数组的对象有 DOM 操作返回的 NodeList 集合,以及函数内部的 arguments 对象。

    let arrayLike = {
        '0': 'a',
        '1': 'b',
        '2': 'c',
        length: 3
    };
    
    // ES5的写法
    var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
    
    // ES6的写法
    let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
    
    Array.from('hello');
    // ['h', 'e', 'l', 'l', 'o']
    
    let namesSet = new Set(['a', 'b']);
    Array.from(namesSet); // ['a', 'b']

    Array.from 还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。

    let arrayLike = {
        '0': 1,
        '1': 2,
        '2': 3,
        length: 3
    };
    Array.from(arrayLike, x => x * x); // [ 1, 4, 9 ]

    Array.of()

    Array.of 方法用于将一组值,转换为数组。这个方法的主要目的,是弥补数组构造函数 Array()的不足。因为参数个数的不同,会导致 Array()的行为有差异。

    Array.of() // []
    Array.of(undefined) // [undefined]
    Array.of(1) // [1]
    Array.of(1, 2) // [1, 2]

    copyWithin()

    参数:

    • target(必需):必需。复制到指定目标索引位置。
    • start(可选):可选。元素复制的起始位置。
    • end(可选):可选。停止复制的索引位置(默认为array.length)。如果为负值,表示倒数。

    这三个参数都应该是数值,如果不是,会自动转为数值。

    var result = [1, 2, 3, 4, 5].copyWithin(0, 3) 
    console.log(result)//[4,5,3,4,5]

    find() 和 findIndex()

    数组实例的 find 方法,用于找出第一个符合条件的数组成员,如果没有符合条件的成员,则返回 undefined。

    findIndex 方法返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。

    [1, 4, -5, 10].find(n => n < 0); // -5
    [1, 4, -5, 10].findIndex(n => n < 0); // 2

    两个方法都可以接受第二个参数,用来绑定回调函数的 this 对象。

    function f(v){
      return v > this.age;
    }
    let person = {name: 'John', age: 20};
    [10, 12, 26, 15].find(f, person);  // 26

    这两个方法都可以发现 NaN,弥补了数组的 indexOf 方法的不足。

    fill() 填充数组

    fill 方法使用给定值,填充一个数组。fill 方法可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。如果填充的类型为对象,那么被赋值的是同一个内存地址的对象,而不是深拷贝对象,改变数组中的一项,则所有项都改变。

    let arr = Array.of(1, 2, 3).fill({
        num: 20
    });
    
    console.log(arr); // [ { num: 20 }, { num: 20 }, { num: 20 } ]
    
    arr[0].num = 10;
    console.log(arr); // [ { num: 10 }, { num: 10 }, { num: 10 } ]

    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"

    includes()

    includes 方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的 includes 方法类似。该方法的第二个参数表示搜索的起始位置,第二参数是负数,取它的倒数,第二参数大于数组长度,取 0。

    [1, 2, 3].includes(3, -1); // true

    flat(),flatMap()

    flat()默认只会“拉平”一层,如果想要“拉平”多层的嵌套数组,可以将 flat()方法的参数写成一个整数,表示想要拉平的层数,默认为 1。

    flat()的参数为 2,表示要“拉平”两层的嵌套数组。如果不管有多少层嵌套,都要转成一维数组,可以用 Infinity 关键字作为参数。

    [1, [2, [3]]].flat(Infinity);
    // [1, 2, 3]

    flatMap()先遍历数组,再“拉平”一层,也只能拉平一层。参数与 map()方法类似。

    [2, 3, 4].flatMap(x => [x, x * 2]); // [2, 4, 3, 6, 4, 8]
    
    // 相当于
    [2, 3, 4].map(x => [x, x * 2]).flat(); // [2, 4, 3, 6, 4, 8]

    对象扩展

    属性简洁表示法

    const a = 1;
    const b = 2;
    
    const c = {a, b};
    // 等同于
    const c = {a: a, b: b};
    
    const o = {
      method() {
        return "Hello!";
      }
    };
    // 等同于
    const o = {
      method: function() {
        return "Hello!";
      }
    };
    
    function f(x, y) {
      return {x, y};
    }
    // 等同于
    function f(x, y) {
      return {x: x, y: y};
    }

    对象的扩展运算符

    对象扩展符类似数组扩展符,主要用于解构赋值。

    let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
    x // 1
    y // 2
    z // { a: 3, b: 4 }
    
    let ab = { ...a, ...b };
    // 等同于
    let ab = Object.assign({}, a, b);

    Object.is()

    它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。

    Object.is('str', 'str'); // true
    Object.is({}, {}); // false

    不同之处只有两个:一是+0不等于-0,二是NaN等于自身。

    +0 === -0 //true
    NaN === NaN // false
    
    Object.is(+0, -0) // false
    Object.is(NaN, NaN) // true

    Object.assign()

    Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。

    Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。

    由于undefined和null无法转成对象,所以如果它们作为首参数,就会报错。

    const target = { a: 1, b: 1 };
    
    const source1 = { b: 2, c: 2 };
    const source2 = { c: 3 };
    
    Object.assign(target, source1, source2);
    target // {a:1, b:2, c:3}

    常见用途:

    • 为对象添加属性和方法
    • 克隆或合并对象
    • 给属性指定默认值

    Object.keys(),Object.values(),Object.entries()

    ES5 引入了Object.keys方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。

    var obj = { foo: 'bar', baz: 42 };
    Object.keys(obj)
    // ["foo", "baz"]

    Object.values方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。

    const obj = { foo: 'bar', baz: 42 };
    Object.values(obj)
    // ["bar", 42]
    const obj = { 100: 'a', 2: 'b', 7: 'c' };
    Object.values(obj)
    // ["b", "c", "a"]

    上面代码中,属性名为数值的属性,是按照数值大小,从小到大遍历的,因此返回的顺序是b、c、a。

    Object.values只返回对象自身的可遍历属性。

    const obj = Object.create({}, {p: {value: 42}});
    Object.values(obj) // []

    上面代码中,Object.create方法的第二个参数添加的对象属性(属性p),如果不显式声明,默认是不可遍历的,因为p的属性描述对象的enumerable默认是false,Object.values不会返回这个属性。只要把enumerable改成true,Object.values就会返回属性p的值。

    const obj = Object.create({}, {p:
      {
        value: 42,
        enumerable: true
      }
    });
    Object.values(obj) // [42]

    Object.entries()方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。

    const obj = { foo: 'bar', baz: 42 };
    Object.entries(obj)
    // [ ["foo", "bar"], ["baz", 42] ]

    除了返回值不一样,该方法的行为与Object.values基本一致。

    Object.fromEntries()

    Object.fromEntries()方法是Object.entries()的逆操作,用于将一个键值对数组转为对象。

    Object.fromEntries([
      ['foo', 'bar'],
      ['baz', 42]
    ])
    // { foo: "bar", baz: 42 }
  • 相关阅读:
    IIS发布问题解决
    创建Core项目使用IdentityServer4
    通过数据库名称字符串 反射获取数据并刷新对应缓存
    MVC模式下unity配置,报错“No connection string named '**Context' could be found in the application config file”
    Docker巨轮的航行之路-基础知识篇
    C#之LINQ
    Js调试中不得不知的Console
    jQuery中是事件绑定方式--on、bind、live、delegate
    前端常用技术概述--Less、typescript与webpack
    ES6学习之变量的解构赋值
  • 原文地址:https://www.cnblogs.com/moqiutao/p/12264897.html
Copyright © 2020-2023  润新知