ES6对象扩展, 对象链式判断,Object.assign()等方法

文章目录

  • ES6 对象的扩展
    • 1.0 属性的简洁表示法
    • 2.0 属性名表达式
    • 3.0 属性的可枚举性和遍历
    • 4.0 super 关键字
    • 4.0 对象的解构赋值
    • 5.0 对象的扩展运算符
    • 6.0 对象的链判断运算符
      • 6.1 对象的链判断有三种写法: 一
      • 6.2 对象链判断三种写法: 二
      • 6.3 对象链判断三种写法: 三
      • 6.4对象的链判断符的几个注意点
    • 7.0 Null 判断运算符
  • 对象的新增方法
    • 1. Object.is()
    • 2. Object.assign()
      • 2.1. Object.assign()的注意点
      • 2.2 Object.assign() 常见用途
    • 3. Object.getOwnPropertyDescriptors()
    • 4. `__proto__`属性, Object.setPrototypeOf,Object.getPrototypeOf
      • 4.1 `__proto__`属性
      • 4.2 Object.setPrototypeOf()
      • 4.3 Object.getPrototypeOf()
    • 5.0 Object.keys(), Object.values(),Object.entries()
      • 5.1 Object.keys()
      • 5.2 Object.values() 方法
      • 5.3 Object.entries()
    • 6.0 Object.fromEntries()
  • 总结:

ES6 对象的扩展

1.0 属性的简洁表示法

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

const foo = 'bar';
const baz = {foo};
baz // {foo: "bar"}

// 等同于
const baz = {foo: foo};

2.0 属性名表达式

JavaScript 定义对象的属性,有两种方法。

const obj = {}
// 方法一
obj.foo = true;
// 方法二
obj['a' + 'bc'] = 123;
console.log(obj); // { foo: true, abc: 123 }

上面代码是:

  • 方法一是直接使用标识符作为属性名.

  • 方法二是用表达式作为属性名, 这时要将表达式写在 方括号 里.

但是, 如果使用字面量方式定义对象(使用大括号), 在ES5中只能用方法一()标识符定义属性

var obj = {
  foo: true,
  abc: 123
};

ES6允许字面量方式定义对象时, 用方法二(表达式)作为对象的属性名, 即把表达式放在 方括号内

let propKey = 'foo';
let obj = {
    [propKey]: true,
    ['a' + 'bc']: 123
};
console.log(obj); // { foo: true, abc: 123 }

注意:

属性名表达式如果是一个对象, 默认情况下, 自动会将对象转化为[Object,Object] 这一点要特别小心.

const keyA = {a: 1};
const keyB = {b: 2};

const myObject = {
    [keyA]: 'valueA',
    [keyB]: 'valueB'
};
console.log(myObject); // { '[object Object]': 'valueB' }

上面代码中, [keyA][keyB 得到 的都是 [object Object], 所以 [keyB] 会把 [keyA] 覆盖掉, 而 myObject 最后只有一个 [Object,Object] 属性.

3.0 属性的可枚举性和遍历

  1. 可枚举性

    对象的每个属性都有一个描述对象(descriptor), 用来控制该属性的行为. Object.getOwnPropertyDescriptor 方法可以获取该属性的描述对象

    let myObj = {
        a:'123',
        b: '参数b'
    }
    console.log(Object.getOwnPropertyDescriptor(myObj, 'a'));
    // 最后打印出
    /**
     * { value: '123',
     * writable: true,
     * enumerable: true,
     * configurable: true }
     */
    

    描述对象的 enumerable 属性, 称为 "可枚举"属性, 如果该属性为false , 就表示某些操作会忽略当前属性.

    getOwnPropertyDescriptorsgetOwnPropertyDescriptor 类似, 只不过前者返回所有属性的描述对象.

  2. 属性的遍历

ES6 一共有5中方法可以遍历对象的属性

  • for…in

    for...in 循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。
    
  • Object.keys(obj)

    Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。
    
  • Object.getOwnPropertyNames(obj)

    Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。
    
  • Object.getOwnPropertySymbols(obj)

    Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性的键名。
    
  • Reflect.ownKeys(obj)

    Reflect.ownKeys返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举
    

以上的 5 种方法遍历对象的键名,都遵守同样的属性遍历的次序规则。

  1. 首先遍历所有数值键,按照数值升序排列
  2. 其次遍历所有字符串键,按照加入时间升序排列
  3. 最后遍历所有 Symbol 键,按照加入时间升序排列
Reflect.ownKeys({ [Symbol()]:0, b:0, 10:0, 2:0, a:0 })
// ['2', '10', 'b', 'a', Symbol()]

4.0 super 关键字

我们知道, this 关键字总是指向函数所在的当前对象, ES6又新增了另一个类似的关键字 super, 指向当前对象的原型对象.

const proto = {
    foo: 'hello'
};

const obj = {
    foo: 'world',
    find() {
        return super.foo;
    }
};

Object.setPrototypeOf(obj, proto);
console.log(obj.find()); // "hello

上面代码中, 对象 obj.find() 方法之中, 通过 super.foo 引入了原型对象的 foo 属性.

注意: super 关键字表示原型对象时, 只能用在对象的方法之中, 用在其他地方都会报错

// 报错
const obj = {
  foo: super.foo
}

// 报错
const obj = {
  foo: () => super.foo
}

// 报错
const obj = {
  foo: function () {
    return super.foo
  }
}

上面三种super的用法都会报错,因为对于 JavaScript 引擎来说,这里的super都没有用在对象的方法之中。第一种写法是super用在属性里面,第二种和第三种写法是super用在一个函数里面,然后赋值给foo属性。目前,只有对象方法的简写法可以让 JavaScript 引擎确认,定义的是对象的方法。

4.0 对象的解构赋值

对象的解构赋值用于从一个对象取值,相当于将目标对象自身的所有可遍历的(enumerable)、但尚未被读取的属性分配到指定的对象上面。所有的键和它们的值,都会拷贝到新对象上面。

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }

上面代码中,变量z是解构赋值所在的对象。它获取等号右边的所有尚未读取的键(ab),将它们连同值一起拷贝过来

解构赋值必须是最后一个参数,否则会报错。

let { ...x, y, z } = someObject; // 句法错误
let { x, ...y, ...z } = someObject; // 句法错误

注意,解构赋值的拷贝是浅拷贝,即如果一个键的值是复合类型的值(数组、对象、函数)、那么解构赋值拷贝的是这个值的引用,而不是这个值的副本

5.0 对象的扩展运算符

对象的扩展运算符(...) 用于取出参数对象的所有可遍历属性, 拷贝到当前的对象中

const obj = {
    name: 'Gene',
    age: 18,
    sex: 'male',
}
const destructorObj = {...obj}
console.log(destructorObj); // { name: 'Gene', age: 18, sex: 'male' }

由于数组也是特殊的 对象, 所以对象的扩展运算符也可以用于数组

const arr = ["name", "age", "sex", 1]
const desturctorArr = {...arr}
console.log(desturctorArr); // { '0': 'name', '1': 'age', '2': 'sex', '3': 1 }

对象的扩展运算符等同于使用 Object.assign() 方法.

let aClone = { ...a };
// 等同于
let aClone = Object.assign({}, a);

6.0 对象的链判断运算符

编程中, 如果读取对象内部的某个属性, 往往需要判断一下该对象是否存在. 比如, 要读取 message.body.user.firstName, 安全的写法是写成下面这样.

const obj = {
    name: 'Gene',
    age: 18,
    sex: 'male',
}
const name = (obj && obj.name) || '抱歉, 您所访问的对象name不存在'
const hobby = (obj && obj.hobby) || '抱歉, 您所访问的对象 hobby 爱好不存在'
console.log(name); // Gene
console.log(hobby); // 抱歉, 您所访问的对象 hobby 爱好不存在

如果使用三元运算符判断一个对象是否存在, 比较麻烦, **因此 ES2020 加入了 链判断运算符**, 能简化判断

6.1 对象的链判断有三种写法: 一

  • obj?.prop // 对象属性
  • obj?.[expr] // 同上
  • func?.(...args) // 函数或对象方法的调用

下面是判断对象方法是否存在, 如果存在就立即执行

# 链判断运算符第一种写法
const person = {
    name: 'Gene',
    sayHi() {
        console.log('可以看到判断完, 对象法法直接执行了');
    }
};
person.sayHi?.() // 可以看到判断完, 对象法法直接执行了
person.sayHello?.() // 因为person对象里没有 sayHello 方法, 故此行代码不执行.

6.2 对象链判断三种写法: 二

# 链判断第二种写法
const person = {
    name: 'Gene',
    sayHi() {
        console.log('可以看到判断完, 对象法法直接执行了');
    }
};
console.log(person?.['name']); // Gene
console.log(person?.['age']); // undefined

6.3 对象链判断三种写法: 三

# 链判断第三种写法
  // 函数的调用
	function add(a, b) {
     return a + b
    }
    const arr = [1,2]
    console.log(add?.(...arr));

# ------------------------------------
  // 对象方法的调用
	const person = {
    	sayHi(name) {
        	console.log(`hello, 你好, 我是${name}... ...`);
    	},
   	 	eat(food) {
        	console.log(`我早上吃的${food} ... ...`);
    	}
	}
    person.sayHi?.('杨阳') // hello, 你好, 我是杨阳... ...
    person.eat?.('包子和鸡蛋') // 我早上吃的包子和鸡蛋 ... ...
    person.run?.() // 不存在run方法, 该方法就不会执行

6.4对象的链判断符的几个注意点

  1. 短路机制

    a?.[++x]
    // 等同于
    a == null ? undefined : a[++x]
    

    上述代码中, 如果aundefinednull 那么结果就会返回 undefinednull, 后面的 ++x 就会被短路, 不再执行.

  2. delete 运算符

    delete a?.b
    // 等同于
    a == null ? undefined : delete a.b
    

    上面代码中,如果aundefinednull,会直接返回undefined,而不会进行delete运算。

  3. 括号的影响

    如果属性链有圆括号, 链判断运算符对圆括号外部没有影响, 只对圆括号内部有影响

    (a?.b).c
    // 等价于
    (a == null ? undefined : a.b).c
    

    上面代码中,?.对圆括号外部没有影响,不管a对象是否存在,圆括号后面的.c总是会执行。

    一般来说,使用?.运算符的场合,不应该使用圆括号。

  4. **使用链判断会报错的场合 **

以下写法是禁止的, 会报错.

// 构造函数
new a?.()
new a?.b()

// 链判断运算符的右侧有模板字符串
a?.`{b}`
a?.b`{c}`

// 链判断运算符的左侧是 super
super?.()
super?.foo

// 链运算符用于赋值运算符左侧
a?.b = c
  1. 右侧不得为十进制数值

为了保证兼容以前的代码,允许foo?.3:0被解析成foo ? .3 : 0,因此规定如果?.后面紧跟一个十进制数字,那么?.不再被看成是一个完整的运算符,而会按照三元运算符进行处理,也就是说,那个小数点会归属于后面的十进制数字,形成一个小数

7.0 Null 判断运算符

ES2020 添加的Null运算符

读取对象属性的时候,如果某个属性的值是nullundefined,有时候需要为它们指定默认值。常见做法是通过||运算符指定默认值。

const headerText = response.settings.headerText || 'Hello, world!';
const animationDuration = response.settings.animationDuration || 300;
const showSplashScreen = response.settings.showSplashScreen || true;

上面的三行代码都通过||运算符指定默认值,但是这样写是错的。开发者的原意是,只要属性的值为nullundefined,默认值就会生效,但是属性的值如果为空字符串或false0,设置的默认值也会生效。

为了避免这种情况, ES2020 引入了一个新的 Null 判断运算符 ??. 它的行为类似 ||, 但是只有运算符左侧的值为 null 或者 undefined 时, 才会返回等号右侧的值. 避免了属性是 空字符串和 false 时执行等号右边的赋值运算.

const obj = {
    name: 'Gene'
}
console.log(obj.name ?? '我是杨阳'); // 返回正确值 Gene
console.log(obj.age ?? 25); // age是undefined, 所以最后打印 25

null 运算符的一个目的, 就是跟链判断符 ?. 配合使用, 为 nullundefined 的值会设置默认值.

const animationDuration = response.settings?.animationDuration ?? 300;

上面代码中,response.settings如果是nullundefined,就会返回默认值300。

?? 运算符有一个运算符优先级问题, 它与 &&|| 的优先级孰高孰低. 现在的规则是, 如果多个逻辑运算符一起使用, 必须使用大括号表明优先级. 否则会报错

// 报错
lhs && middle ?? rhs
lhs ?? middle && rhs
lhs || middle ?? rhs
lhs ?? middle || rhs

上面四个表达式都会报错,必须加入表明优先级的括号。

对象的新增方法

1. Object.is()

ES5比较两个值是否相等, 只有两个运算符: 相等运算符 == 和严格相等运算符 ===. 它们都要缺点, 前者会自动转换数据类型, 后者的 NaN 不等于自身, 以及+0 等于-0 . JavaScript缺乏一种运算, 在所有环境中, 只要两个值是一样的, 它们就应该相等.

ES6提出 "Same-value equality“(同值相等)算法, 来解决这个问题. Object.is() 就是部署这个算法的新方法. 它用来比较两个值是否严格相等, 与严格运算符 === 的行为基本一致.

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

不同之处只有两个: 一是+0 不得恩顾-0 , 而是 NaN 等于自身

+0 === -0 //true
NaN === NaN // false

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

2. Object.assign()

Object的拷贝实现的是浅拷贝.

一些函数库提供Object.assign的定制版本(比如 Lodash 的_.defaultsDeep方法),可以得到深拷贝的合并

基本用法

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

const target = {
    name: 'Gene',
    age: 25
};
const source1 = {
    sex: 'male',
}
const source2 = {
    hobby: 'sleep'
}
Object.assign(target, source1, source2)
console.log(target); // { name: 'Gene', age: 25, sex: 'male', hobby: 'sleep' }

Object.assign 方法的第一个参数是目标对象, 后面的参数都是源对象.

注意: 如果目标对象与源对象有同名属性, 或多个源对象有同名属性, 则后面的属性会覆盖前面的属性.

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.assign 会直接返回该参数.

const obj = {a: 1};
Object.assign(obj) === obj // true

如果该参数不是对象, 则会先转成对象, 然后返回

console.log(Object.assign(2)); // [Number: 2]
console.log(typeof Object.assign(2)); // "object

由于 undefinednull 无法转成对象, 所以, 如果它们作为参数, 会报错.

Object.assign(undefined) // 报错 Cannot convert undefined or null to object
Object.assign(null) // 报错"  Cannot convert undefined or null to object

如果非对象参数出现在源对象的位置(即非首参数),那么处理规则有所不同。首先,这些参数都会转成对象,如果无法转成对象,就会跳过。这意味着,如果undefinednull不在首参数,就不会报错。

let obj = {a: 1};
Object.assign(obj, undefined) === obj // true
console.log(obj); // { a: 1 }
Object.assign(obj, null) === obj // true
console.log(obj); // { a: 1 }

其他类型的值(即数值、字符串和布尔值)不在首参数,也不会报错。但是,除了字符串会以数组形式,拷贝入目标对象,其他值都不会产生效果。

const v1 = 'abc';
const v2 = true;
const v3 = 10;

const obj = Object.assign({}, v1, v2, v3);
console.log(obj); // { "0": "a", "1": "b", "2": "c" }

上面代码中,v1v2v3分别是字符串、布尔值和数值,结果只有字符串合入目标对象(以字符数组的形式),数值和布尔值都会被忽略。这是因为只有字符串的包装对象,会产生可枚举属性。

Object.assign拷贝的属性是有限制的,只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)。

属性名为 Symbol 值的属性,也会被Object.assign拷贝。

2.1. Object.assign()的注意点

  1. Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。

  2. 同名属性的替换

    对于这种嵌套的对象,一旦遇到同名属性,Object.assign的处理方法是替换,而不是添加。

  3. 数组的处理

Object.assign可以用来处理数组,但是会把数组视为对象。

Object.assign([1, 2, 3], [4, 5])
// [4, 5, 3]
  1. 取值函数的处理

    Object.assign只能进行的复制,如果要复制的值是一个取值函数,那么将求值后再复制。

    const source = {
      get foo() { return 1 }
    };
    const target = {};
    
    Object.assign(target, source)
    // { foo: 1 }
    

    上面代码中,source对象的foo属性是一个取值函数,Object.assign不会复制这个取值函数,只会拿到值以后,将这个值复制过去。

2.2 Object.assign() 常见用途

  1. 为对象添加属性

    class Point {
      constructor(x, y) {
        Object.assign(this, {x, y});
      }
    }
    

    ​ 上面方法通过Object.assign方法,将x属性和y属性添加到Point类的对象实例。

  2. 为对象添加方法

    Object.assign(SomeClass.prototype, {
      someMethod(arg1, arg2) {
        ···
      },
      anotherMethod() {
        ···
      }
    });
    
    // 等同于下面的写法
    SomeClass.prototype.someMethod = function (arg1, arg2) {
      ···
    };
    SomeClass.prototype.anotherMethod = function () {
      ···
    };
    
  3. 克隆对象

function clone(origin) {
  return Object.assign({}, origin);
}
  1. 合并多个对象

    将多个对象合并到某个对象

    const merge =
      (target, ...sources) => Object.assign(target, ...sources);
    

    如果希望合并后返回一个新对象

    const merge =
      (...sources) => Object.assign({}, ...sources);
    

3. Object.getOwnPropertyDescriptors()

ES5 的Object.getOwnPropertyDescriptor()方法会返回某个对象属性的描述对象(descriptor)。ES2017 引入了Object.getOwnPropertyDescriptors()方法,返回指定对象所有自身属性(非继承属性)的描述对象。

const obj = {
  foo: 123,
  get bar() { return 'abc' }
};

Object.getOwnPropertyDescriptors(obj)
// { foo:
//    { value: 123,
//      writable: true,
//      enumerable: true,
//      configurable: true },
//   bar:
//    { get: [Function: get bar],
//      set: undefined,
//      enumerable: true,
//      configurable: true } }

上面代码中,Object.getOwnPropertyDescriptors()方法返回一个对象,所有原对象的属性名都是该对象的属性名,对应的属性值就是该属性的描述对象。

4. __proto__属性, Object.setPrototypeOf,Object.getPrototypeOf

4.1 __proto__属性

JS 语言的对象继承是通过原型链实现的. ES6提供了更多的原型对象的操作方法.

// es5 的写法
const obj = {
    sayHi: function (message) {
        console.log('hello, 你好' + message);
    }
}
obj.__proto__.eat = function (food) {
    console.log('我吃过饭了吃的' + food);
}
obj.eat('水饺') // 我吃过饭了吃的水饺

# ----------------
// es6 的写法
var obj = Object.create(someOtherObj);
obj.method = function() { ... };

该属性没有写入 ES6 的正文,而是写入了附录,原因是__proto__前后的双下划线,说明它本质上是一个内部属性,而不是一个正式的对外的 API,只是由于浏览器广泛支持,才被加入了 ES6。标准明确规定,只有浏览器必须部署这个属性,其他运行环境不一定需要部署,而且新的代码最好认为这个属性是不存在的。因此,无论从语义的角度,还是从兼容性的角度,都不要使用这个属性,而是使用下面的Object.setPrototypeOf()(写操作)、Object.getPrototypeOf()(读操作)、Object.create()(生成操作)代替

如果一个对象本身部署了__proto__属性,该属性的值就是对象的原型。

Object.getPrototypeOf({ __proto__: null })
// null

4.2 Object.setPrototypeOf()

Object.setPrototypeOf() 方法的作用与 __proto__相同, 用来设置一个对象的原型对象(prototype), 返回参数对象本身. 它是 es6 正式推荐的设置原型对象的方法.

const Animal = {
    name: 'Gene123',
    age: 17
}
const person = {}

Object.setPrototypeOf(person, Animal)
console.log(person.__proto__ == Animal); // true
console.log(person.__proto__ === Animal); // true
console.log(person.__proto__); // {name: "Gene123", age: 17}

该方法等同于下面的函数

function setPrototypeOf(obj, proto) {
  obj.__proto__ = proto;
  return obj;
}

4.3 Object.getPrototypeOf()

该方法与Object.setPrototypeOf方法配套, 用于读取一个对象的原型对象.

function Animal(name, age) {
    this.name = name
    this.age = age
}

const person = new Animal('Gene', 18)
console.log(Object.getPrototypeOf(person) === Animal.prototype); // true
Object.setPrototypeOf(person, Object.prototype)
console.log(Object.getPrototypeOf(person) === Animal.prototype); // false

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

5.1 Object.keys()

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

const obj = {
    name: 'Gene',
    age: 26
}
console.log(Object.keys(obj)); // [ 'name', 'age' ]

ES2017 引入了跟Object.keys配套的Object.valuesObject.entries,作为遍历一个对象的补充手段,供for...of循环使用。

// 拿出Object中的 keys() 方法, values()方法和 entries()方法
let {keys, values, entries} = Object;
let obj = {a: 1, b: 2, c: 3};

for (let key of keys(obj)) {
    console.log(key); // 'a', 'b', 'c'
}

for (let value of values(obj)) {
    console.log(value); // 1, 2, 3
}

for (let [key, value] of entries(obj)) {
    console.log([key, value]); // ['a', 1], ['b', 2], ['c', 3]

5.2 Object.values() 方法

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

const obj = {
    name: 'Gene',
    age: 18
}
console.log(Object.values(obj)); // [ 'Gene', 18 ]

如果Object.values方法的参数是一个字符串,会返回各个字符组成的一个数组

Object.values('foo')
// ['f', 'o', 'o']

5.3 Object.entries()

Object.entries() 方法返回一个数组, 成员是参数对象自身的所有可枚举属性的 键值对数组

const obj = {
    name: 'Gene',
    age: 18,
}
console.log(Object.entries(obj)) // [ [ 'name', 'Gene' ], [ 'age', 18 ] ]

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

Object.entries 方法的另一用处是, 将对象转化为 Map 结构

const obj = { foo: 'bar', baz: 42 };
const map = new Map(Object.entries(obj));
console.log(map); // Map { 'foo' => 'bar', 'baz' => 42 }

6.0 Object.fromEntries()

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

const twoDimensionArr = [
    ['name', 'Gene'],
    ['age', 18],
    ['gender', 'male']
]
console.log(Object.fromEntries(twoDimensionArr)); // {name: "Gene", age: 18, gender: "male"}

该方法的主要目的, 是将键值对的 数据结构, 还原为对象, 因此特别适合将 Map 结构转化为对象.

该方法的另一个用处是配合 URLSearchParams 对象, 将查询字符串转化为对象.

console.log(Object.fromEntries(new URLSearchParams('name=Gene&age=18&pwd=123')));
// {name: "Gene", age: "18", pwd: "123"}

URLSearchParams() API主要是用于处理URL之中的查询字符串,即问号之后的部分内容

console.log(new URLSearchParams('?name=Gene&age=18&pwd=123'));
// URLSearchParams { 'name' => 'Gene', 'age' => '18', 'pwd' => '123' }

总结:

上一章: 数组的扩展, Array.from方法, 数组实例的flat方法

下一章: ES6 Symbol函数, 消除魔法字符串解耦

交流学习添加微信(备注技术交流学习): Gene199302
ES6对象扩展, 对象链式判断,Object.assign()等方法_第1张图片

该博客为学习阮一峰 ES6入门课所做的笔记记录, 仅用来留作笔记记录和学习理解

你可能感兴趣的:(ES6)