ES6实用方法Object.assign、defineProperty、Symbol

1.合并对象 - Object.assign()
介绍
  • assign方法可以将多个对象(字典),语法:Object.assign(srcObj,obj1,obj2…)
  • 对于重复的键将会被覆盖(尤其注意对象被覆盖),对于可枚举(迭代)参数(被合并对象)若不是对象则自动转换成对象合并(如string,[]),对于不可枚举参数(undefined,null)会自动跳过。
  • 若源对象(第一个参数)不可枚举则会报错
let srcObj= {
    
     a: 'a',b:'b',obj:{
    
    title:"我要被覆盖了"} },
obj1 = {
    
     b: 2 }, 
obj2 = {
    
     c: 3 },
str3 = "字符串",
num4 = 5;
obj = {
    
    newTitle:"我是新的title"} 

// 1.合并、重复覆盖、自动转换成对象合并、自动跳过举例:
console.log(Object.assign(srcObj, obj1 , obj2, str3, num4,obj));
// {a:'a',b:'2',c:3,0: "字",1: "符",2: "串",obj:{newTitle:"我是新的title"}}

// 2.报错
Object.assign(null, obj1 , obj2 )) 
进阶
  • 当声明一个对象时,它的enumerable属性默认是true,我们也可以显示的将它设为false,所以说对象不一定都是可迭代的(眼见不一定为实),但可以通过’.'取到。
  • 若拷贝类型是Symbol 类型也会被拷贝。Symbol :和int、float等一样是数据类型,只不过他是隐藏类型,直接访问是取不到的
// 1.跳过不可迭代的对象
var unEnumer = Object.defineProperty({
    
    }, "k", {
    
    
          enumerable: false,
          value: "hello"
        }), // {k:"hello"}
    // 这样定义对象,任何值都能作为键(被视为字符串)
    enumer = Object.defineProperty({
    
    }, null,{
    
    
          enumerable: true,
          value: "hello"
        }) // {"null":"hello"}
console.log(Object.assign( {
    
     b: "c" },unEnumer ,enumer ));
// {b: "c",null: "hello"}

// 2.合并Symbol 类型,既可以当键也可以当值
 console.log(Object.assign({
    
     a: 'b' }, {
    
     [Symbol('c')]: 'd' },{
    
    'e':Symbol('f')}))
// {a: "b", e: Symbol(f), Symbol(c): "d"}
注意
  • 拷贝后的数据间的影响关系
  • 拷贝对象是数组则按照字典处理,数组很好理解成字典,如[‘a’,‘b’,‘c’],实际上会自动分配键,等价于{0:‘a’,1:‘b’,2:‘c’},所以处理规则同字典一样。
  • 对取值函数与赋值函数的处理
// 1.影响关系
var obj1 = {
    
     a: 1 },obj2={
    
    b:{
    
    c:1}};
var obj = Object.assign({
    
    }, obj1,obj2);
obj1.a = 2 // 不影响
obj2.b.c = 3 // 影响
console.log(obj,obj1,obj2) // {a: 1,b: {c: 3}}

// 2.处理数组
console.log(Object.assign([1, 2, 3], [4, 5])) // 合并完还是数组 [4, 5, 3]
console.log(Object.assign({
    
    0:1,3:3}, [4, 5])) // 合并完是对象 {0: 4, 1: 5, 3: 3}
console.log(Object.assign( [4, 5],{
    
    0:1,3:3})) // 合并完还是数组 [1, 5, empty, 3]  empty?

// 3.对取值函数处理和赋值函数处理
var obj1={
    
    get foo(){
    
    return "a"}},
obj2={
    
    foo:()=>{
    
    return "a"}}
console.log(obj1) // foo: "a",obj1.foo得到的是函数执行结果,计算属性原理?
console.log(obj2) // foo: ƒ foo(),obj2.foo得到的是函数地址
console.log(Object.assign({
    
    },{
    
    get obj1(){
    
    return "a"}},{
    
    obj2:()=>{
    
    return "a"}})) // {obj1: "a",obj2: ƒ obj2()}
用途
  • 为对象添加属性,方法
  • 克隆对象,结合新语法合并多个对象
  • 为属性指定默认值
// 1.为对象同时添加(更新)多个属性、方法
var obj = {
    
    title:"标题",dateStamp:"2020/5/22"},
newProp = {
    
    get dateStamp(){
    
     return Date.now()},text:"新属性",fun1(){
    
    return "新方法"}};
console.log(Object.assign(obj, newProp)) // {title: "标题", dateStamp: 1590119249783, text: "新属性", fun1: ƒ}

// 2.克隆
var obj = {
    
    };
var obj1 = {
    
     a: 1 };
Object.defineProperty(obj1, "k", {
    
    
    enumerable: true,
    // value: "hello",
    get() {
    
    
      console.log("获取obj1的k值");
    } // 当使用了getter或setter方法,不允许使用writable和value这两个属性?   
    });
console.log(Object.assign(obj, obj1)); // 获取obj1的k值 {a: 1, k: undefined}
console.log(Object.assign(obj, obj1).k); // 获取obj1的k值 undefined
console.log(obj1.k); // 获取obj1的k值 undefined
// 采用这种方法克隆,只能克隆原始对象自身的值,不能克隆它继承的值(什么意思?)

// 3.为对象指定默认值和属性
const defaultVal = {
    
    
      title: "未定义",
      time: "0"
    };
var obj = {
    
    },
obj1 = {
    
    };
Object.defineProperty(obj1, "title", {
    
    
  enumerable: true,
  // value: "hello",
  get() {
    
    
    console.log("获取obj的title值");
    return "标题"
  }
});
// 注意顺序,先默认值,再配置属性,obj在最后
console.log(Object.assign({
    
    }, defaultVal,obj1,obj));
2.定义对象 - Object.defineProperty(obj, prop, descriptor)

定义属性:Object.defineProperty(obj, prop, descriptor)

属性在创建对象时就定义好了,所有特性的默认值都为true;而当使用defineProperty添加的属性,特性的默认值都为false。当使用了getter或setter方法,不允许使用writable和value这两个属性?

obj ,待修改的对象
prop ,带修改的属性名称
descriptor ,待修改属性的相关描述

configurable ,属性是否可配置。可配置的含义包括:是否可以删除属性( delete ),是否可以修改属性的 writable 、 enumerable 、 configurable 属性。 改为false之后,不能删除修改(不可逆)。默认true

enumerable ,属性是否可枚举。可枚举的含义包括:是否可以通过 for…in 遍历到,是否可以通过 Object.keys() 方法获取属性名称,是改为false,for in时不会被遍历,但使用 "."依然可访问。默认true

writable ,是否为可写,改为false,当前属性变为只读。。默认true

value ,属性的默认值。

set ,属性的重写器(暂且这么叫)。一旦属性被重新赋值,此方法被自动调用。

get ,属性的读取器(暂且这么叫)。一旦属性被访问读取,此方法被自动调用。

3.新数据类型- Symbol

Symbol是由ES6规范引入的一项新特性,它的功能类似于一种标识唯一性的ID。

定义
    let s1 = Symbol();
    let s2 = Symbol("another symbol"); // 传入描述信息 可以是任何可以被转型成字符串的值,如:字符串、数字、对象、数组等
    let s3 = Symbol();
    console.log(s1,s2,s3)
    console.log(typeof s1); // 'symbol'
    console.log(s1===s2,s1===s3); // false - 每个Symbol实例都是唯一的。
应用
  • 由于Symbol类型的key是不能通过Object.keys()或者for…in来枚举的,它未被包含在对象自身的属性名集合(property names)之中,所以可以把一些不需要对外操作和访问的属性使用Symbol来定义,作为对象的键(唯一);
  • 因为这个特性,当使用JSON.stringify()将对象转换成JSON字符串的时候,Symbol属性也会被排除在外
  • 定义常量不用再去想值的内容了
  • 安全性高
  • 多模块共享唯一
	const NAME = Symbol("it`s const key");
    const AGE = Symbol("it`s const key");
    let obj = {
    
    [NAME]: "默认名称"};
    obj[AGE] = "赋值年龄";
    // 访问
    console.log(obj[NAME],obj[AGE]) // 默认名称, 赋值年龄
    // 获取所有1
    console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(it`s const key), Symbol(it`s const key)]
    // 获取所有2
    console.log(Reflect.ownKeys(obj)); // [Symbol(it`s const key), Symbol(it`s const key)]

    // 定义常量不用再去想值的内容了
    const id = Symbol(); // id - 唯一

	// 注册全局Symbol,实现多模块共享唯一Symbol
    let s1 = Symbol.for("global_symbol_1"); //注册一个全局Symbol
    let s2 = Symbol.for("global_symbol_1"); //获取全局Symbol,注意描述一直才行
    let s3 = Symbol.for("global_symbol_3");
    console.log(s1 === s2); // true
    console.log(s1 === s3); // false

未完待续…

猜你喜欢

转载自blog.csdn.net/GeniusXYT/article/details/106274219