• Object-API—01


    new 一个对象,查看它原型的构造函数:

     接下来一个一个说:

    (1)Object.assign()——ES6

    Object.assign()方法用于对象的合并,将源对象(第一个参数)的所有可枚举属性,复制到目标对象(后面所有参数)。即将其他对象的属性复制到某个对象中

    1 const obj = {a:1}
    2 const obj01 = {b:2}
    3 const obj02 = {c:3}
    4 Object.assign(obj,obj01,obj02)
    5 console.log(obj);  // {a: 1, b: 2, c: 3}

    注意:

    • 如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
    • 如果只有一个参数,Object.assign()会直接返回该参数
    • 由于undefinednull无法转成对象,所以如果它们作为参数,就会报错。这两个不是出现在第一个目标对象时,处理规则有所不同。这些参数都会转成对象,如果无法转成对象,就会跳过。这意味着,如果undefinednull不在首参数,就不会报错。
    • 其他类型的值(即数值、字符串和布尔值)不在首参数,也不会报错。但是,除了字符串会以数组形式,拷贝入目标对象,其他值都不会产生效果。
      • 1 const v1 = 'abc';
        2 const v2 = true;
        3 const v3 = 10;
        4 
        5 const obj = Object.assign({}, v1, v2, v3);
        6 console.log(obj); // { "0": "a", "1": "b", "2": "c" }
      • 上面代码中,v1v2v3分别是字符串、布尔值和数值,结果只有字符串合入目标对象(以字符数组的形式),数值和布尔值都会被忽略。这是因为只有字符串的包装对象,会产生可枚举属性。
      • 1 Object(true) // {[[PrimitiveValue]]: true}
        2 Object(10)  //  {[[PrimitiveValue]]: 10}
        3 Object('abc') // {0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"}
      • 上面代码中,布尔值、数值、字符串分别转成对应的包装对象,可以看到它们的原始值都在包装对象的内部属性[[PrimitiveValue]]上面,这个属性是不会被Object.assign()拷贝的,只有字符串的包装对象,会产生可枚举的实意义属性,那些属性则会被拷贝
    • Object.assign()拷贝的属性是有限制的,只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)。
      • 1 Object.assign({b: 'c'},
        2   Object.defineProperty({}, 'invisible', {
        3     enumerable: false,
        4     value: 'hello'
        5   })
        6 )
        7 // { b: 'c' }
    • 属性名为 Symbol 值的属性,也会被Object.assign()拷贝。

    (2)Object.create()

    用于在没有构造函数的情况下,也能创建子对象

    语法:

    const 子对象名 = Object.create(父对象)

     create()创建出来的新对象的__proto__被自动设置为create()的参数,也就是自动继承了父对象了

     1 const son = Object.create(father,{
     2     // 这里的格式与Object.defineProperties中格式一样
     3     name: {
     4         value: "张三",
     5         writable:true,
     6         enumerable:true,
     7         configurable:true
     8     },
     9     age:{
    10         value:26,
    11         writable:true,
    12         enumerable:true,
    13         configurable:true
    14     }
    15 })
    16 
    17 console.log(son.type);  //
    18 console.log(son.name);  // 张三
    19 console.log(son.age);  // 26

    说明:

    • create()第二个参数可选,不填就是创建一个空的子对象

    (3)Object.defineProperty() & Object.defineproperties()

    ①Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

    1 const obj ={}
    2 Object.defineProperty(obj,'name',{
    3     value: '张三',
    4     writable:true,
    5     enumerable:true,
    6     configurable:true
    7 })
    8 console.log(obj);  //{name: "张三"}

    说明:

    • value:定义的属性的值
    • writable:属性是否可被修改
    • enumerable:是否可被枚举(无法被for...in..获取到,但是可以直接访问)
    • configurable:控制是否可以修改writable和enumerable
    • 还有另外两个可选键值:get & set :可用于控制属性的修改时控制,vue双向绑定就是基于Object.defineproperty这个方法
      •  1 const obj ={}
         2 let val = ""
         3 
         4 Object.defineProperty(obj,'name',{
         5     enumerable:true,
         6     configurable:true,
         7     get(){
         8         console.log("get:",val);
         9         return val
        10     },
        11     set(newVal){
        12         console.log("set:",newVal);
        13         val=newVal
        14     }
        15 })
        16 
        17 val="赵四"
        18 obj.name=val  // set
        19 console.log(obj.name);  // get

    ②Object.defineproperties用于同时在对象上定义多个属性,用法与defineproperty类似

     1 var obj = {};
     2 Object.defineProperties(obj, {
     3   'property1': {
     4     value: true,
     5     writable: true
     6   },
     7   'property2': {
     8     value: 'Hello',
     9     writable: false
    10   }
    11   // etc. etc.
    12 });

    (4)Object.entries()/Object.fromEntries() & Object.keys() & Object.values()  —ES6

    作用与数组的这三个同名办法相同,都是用来遍历对象的

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

    1 const obj = { foo: 'bar', baz: 42 };
    2 Object.entries(obj)

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

    1         let obj = Object.fromEntries([
    2             ['a', 1], ["b", 2]
    3         ])
    4         console.log(obj);  // {a: 1, b: 2}

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

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

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

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

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

    (5)Object.preventExtensions() & Object.seal() & Object.freeze() 

    这三个属性都是用来控制对象的扩展
    ①Object.preventExtensions():禁止给对象添加新属性

    const obj ={ 
        name:"张三",
        age: 26
     }
    
     Object.preventExtensions(obj)
    
     obj.sex = 1
     console.log(obj);  // {name: "张三", age: 26}  

    说明:

    • 这里没有使用严格模式,所以默认是修改失败的。严格模式下会报错:Uncaught TypeError: Cannot add property sex, object is not extensible

    原理:

      每个对象内部有一个内部属性extensible = true。此方法就是将对象的内部属性extensible = false

    ②Object.seal():禁止添加新属性禁止删除现有属性

     1 const obj ={ 
     2     name:"张三",
     3     age: 26
     4  }
     5 
     6  Object.seal(obj)
     7 
     8  obj.sex = 1
     9  console.log(obj);  // {name: "张三", age: 26}
    10  delete obj.age
    11  console.log(obj);  // {name: "张三", age: 26}

    说明:

    • 同样是在严格模式下会报错

    原理:

    • extensible = false
    • configurable = false

    ③Object.freeze():禁止添加删除属性,不能修改任何属性值

     1 const obj ={ 
     2     name:"张三",
     3     age: 26
     4  }
     5 
     6  Object.freeze(obj)
     7 
     8  obj.sex = 1
     9  console.log(obj);  // {name: "张三", age: 26}
    10  delete obj.age
    11  console.log(obj);  // {name: "张三", age: 26}
    12  obj.name = "李四"
    13  console.log(obj);  // {name: "张三", age: 26}

    说明:

    • 同样的,需要开启严格模式才会报错

    原理:

    • extensible = false
    • configurable = false 
    • writable = false

    (6)Object.getOwnPropertyDescriptor()

    Object.getOwnPropertyDescriptor() 方法返回指定对象上一个自由属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)

    1 const obj = {
    2     name : "张三"
    3 }
    4 const desc = Object.getOwnPropertyDescriptor(obj,'name')
    5 
    6 console.log(desc);  // {value: "张三", writable: true, enumerable: true, configurable: true}

    说明: 

    • 如果指定的属性存在于对象上,则返回其属性描述符对象(property descriptor),否则返回 undefined
    • 可以获取的属性有:
      • writable
      • enumerable
      • configurable
      • value
      • get
      • set
        • get和set这两个访问器函数,只有在定义了才有,否则是undefined

    注意:

    • 在 ES5 中,如果该方法的第一个参数不是对象(而是原始类型),那么就会产生出现 TypeError。而在 ES6,第一个的参数不是对象的话就会被强制转换为对象。

    (7)Object.getOwnPropertyDescriptors()——ES6

    Object.getOwnPropertyDescriptors()方法,返回指定对象所有自身属性(非继承属性)的描述对象。

     1 const obj = {
     2   foo: 123,
     3   get bar() { return 'abc' }
     4 };
     5 
     6 Object.getOwnPropertyDescriptors(obj)
     7 // { foo:
     8 //    { value: 123,
     9 //      writable: true,
    10 //      enumerable: true,
    11 //      configurable: true },
    12 //   bar:
    13 //    { get: [Function: get bar],
    14 //      set: undefined,
    15 //      enumerable: true,
    16 //      configurable: true } }

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

     此方法的实现

    该方法的引入目的,主要是为了解决Object.assign()无法正确拷贝get属性和set属性的问题。

    Object.getOwnPropertyDescriptors()方法的另一个用处,是配合Object.create()方法,将对象属性克隆到一个新对象。这属于浅拷贝

    1         const obj = {name:"张三"}
    2         const clone = Object.create(Object.getPrototypeOf(obj),Object.getOwnPropertyDescriptors(obj))
    3 
    4         console.log(obj === clone);  // false

     说明:

    • getPrototypeOf()方法返回指定对象的原型
    • Object.getOwnPropertyDescriptors(obj)相当于直接获取自身属性当作第二个参数

     - 另外,Object.getOwnPropertyDescriptors()方法可以实现一个对象继承另一个对象。以前,继承另一个对象,常常写成下面这样。

    1 const obj = {
    2   __proto__: prot,
    3   foo: 123,
    4 };

    ES6 规定__proto__只有浏览器要部署,其他环境不用部署。如果去除__proto__,上面代码就要改成下面这样。

     1 const obj = Object.create(prot);
     2 obj.foo = 123;
     3 
     4 // 或者
     5 
     6 const obj = Object.assign(
     7   Object.create(prot),
     8   {
     9     foo: 123,
    10   }
    11 );

     有了Object.getOwnPropertyDescriptors(),我们就有了另一种写法。

    1 const obj = Object.create(
    2   prot,
    3   Object.getOwnPropertyDescriptors({
    4     foo: 123,
    5   })
    6 );

     (8)Object.getOwnPropertyNames()

    Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组

    Object.getOwnPropertyName()返回一个数组,该数组对元素是obj自身拥有的枚举或不可枚举属性名称字符串。数组中枚举属性的顺序与通过for...in...循环(或Oject.keys)迭代对象属性时一致。

     1 var arr = ["a", "b", "c"];
     2 console.log(Object.getOwnPropertyNames(arr).sort()); // ["0", "1", "2", "length"]
     3 
     4 // 类数组对象
     5 var obj = { 0: "a", 1: "b", 2: "c"};
     6 console.log(Object.getOwnPropertyNames(obj).sort()); // ["0", "1", "2"]
     7 
     8 // 使用Array.forEach输出属性名和属性值
     9 Object.getOwnPropertyNames(obj).forEach(function(val, idx, array) {
    10   console.log(val + " -> " + obj[val]);
    11 });
    12 // 输出
    13 // 0 -> a
    14 // 1 -> b
    15 // 2 -> c
    16 
    17 //不可枚举属性
    18 var my_obj = Object.create({}, {
    19   getFoo: {
    20     value: function() { return this.foo; },
    21     enumerable: false
    22   }
    23 });
    24 my_obj.foo = 1;
    25 
    26 console.log(Object.getOwnPropertyNames(my_obj).sort()); // ["foo", "getFoo"]

     如果你只要获取到可枚举属性,可以使用Object.keys或用for...in循环(还会获取到原型链上的可枚举属性,不过可以使用hasOwnProperty()方法过滤掉)。

  • 相关阅读:
    POJ3171 线段树优化dp
    Codeforces Round #590 (Div. 3)
    POJ2777 线段树区间染色问题
    POJ2182 Lost Cows 树状数组,二分
    P1908 逆序对 树状数组
    2019 Multi-University Training Contest 3
    主席树板子题区间第k小
    权值线段树板子题
    KMP板子题
    稀疏贝叶斯
  • 原文地址:https://www.cnblogs.com/codexlx/p/14311749.html
Copyright © 2020-2023  润新知