JS-----Object

505 阅读8分钟

Object.create(proto, [propertiesObject])

方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__

  • proto 新创建对象的原型对象。
  • propertiesObject 可选。需要传入一个对象,该对象的属性类型参照Object.defineProperties()的第二个参数。如果该参数被指定且不为 undefined,该传入对象的自有可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)将为新创建的对象添加指定的属性值和对应的属性描述符。
  let proto = {
      name: 'wang',
      age: 22
  }
  let obj  = Object.create(proto,{
      sex:{
          value: 'boy',
          writable: true
      }
  })
  console.log(obj.name) // wang
  console.log(obj) // { sex: 'boy }

Object.defineProperty(obj, prop, descriptor)

方法直接在一个对象上定义一个新的属性或者修改现有属性,并返回该对象

  • obj 在其上定义或修改属性的对象。
  • prop 要定义或修改的属性的名称或 Symbol
  • descriptor 要定义或修改的属性描述符。

对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。存取描述符是由 getter 函数和 setter 函数所描述的属性。一个描述符只能是这两者其中之一;不能同时是两者。

这两种描述符都是对象。它们共享以下可选键值(默认值是指在使用 Object.defineProperty() 定义属性时,省略字段的默认值):

  • configurable
    当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false

  • enumerable
    当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中,在枚举对象属性时会被枚举到(for...inObject.keys 方法)。默认为 false

  • value
    该属性对应的值。可以是任何有效的 JavaScript 值(数值对象函数等)。默认为 undefined

  • wriatable
    当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变。默认为 false

  • set
    属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。默认为 undefined

  • get
    属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。默认为 undefined

configurableenumerablevaluewritablegetset
数据描述符可以可以可以可以不可以不可以
存取描述符可以可以不可以不可以可以可以
    let obj = {}
    Object.defineProperty(obj, 'sex', {
      value: 'boy',
      writable: true,
      enumerable: false,
      configurable: true, // configurable:true 时可以重新定义属性描述符
    })
    Object.defineProperty(obj, 'age', {
      value: 22,
      writable: false,
      enumerable: true,
      configurable: false // configurable:false 时不能重新定义属性描述符
    })
    console.log(Object.entries(obj)) // [["age", 22]]
    
    // Object.defineProperty(obj, 'age', {
    //     value: 44,
    //     writable: true,
    //     enumerable: false,
    //     configurable: true
    // })
    // 报错 Uncaught TypeError: Cannot redefine property: age  因为第一次定义 'age' 时 configurable:false 所以不能重新定义
    
    Object.defineProperty(obj, 'sex', {
      value: 'boy',
      writable: false,
      enumerable: true,
      configurable: true,
    })
    console.log(Object.entries(obj)) // [   ["sex", "boy"], ["age", 22]]

Object.defineProperties(obj, props)

方法直接在一个对象上定义一个或多个新的属性或修改现有属性,并返回该对象。

  • obj 在其上定义或修改属性的对象。
  • props 要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有两种:数据描述符和访问器描述符(更多详情,请参阅Object.defineProperty())。
  let obj = { sex: 'girl' }
   
  Object.defineProperties(obj, {
     sex: {
        writable: false // false 时赋值语句改变不了sex的值
     },
     age: {
        value: 100,
        writable: true
     }
  })
  obj.sex = 'boy'; // 不能改变值
  obj.age = 22; // 可以改变值
  console.log(obj) // { sex: 'girl', age: 22 }
  
  Object.defineProperties(obj, {
      sex: {
          value: 'boy' // 可以改变值
      },
   })
  console.log(obj) // { sex: 'boy' }
  
  function Archiver() {
  let temperature = null;
  let archive = [];

  Object.defineProperty(this, 'temperature', {
    get: function() {
      console.log('get!');
      return temperature;
    },
    set: function(value) {
        temperature = value;
        archive.push({ val: temperature });
      }
    });

    this.getArchive = function() { return archive; };
  }

  let arc = new Archiver();
  arc.temperature; // 'get!'
  arc.temperature = 11;
  arc.temperature = 13;
  arc.getArchive(); // [{ val: 11 }, { val: 13 }]

Object.getOwnPropertyDescriptor

方法会返回某个对象属性的描述对象

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.assign()无法正确拷贝get属性和set属性的问题。

  const people = {
    set name(value) {
      console.log(value);
    }
  };

  const target = {};
  Object.assign(target, people);

  Object.getOwnPropertyDescriptor(target, 'name')
  // { value: undefined,  这是因为Object.assign方法总是拷贝一个属性的值,而不会拷贝它背后的赋值方法或取值方法。
  //   writable: true,
  //   enumerable: true,
  //   configurable: true }

Object.getOwnPropertyDescriptors()方法配合Object.defineProperties()方法,就可以实现正确拷贝。

  const source = {
    set name(value) {
      console.log(value);
    }
  };

  const target = {};
  Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
  Object.getOwnPropertyDescriptor(target, 'name')
  // { get: undefined,
  //   set: [Function: set name],
  //   enumerable: true,
  //   configurable: true }

Object.is()

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

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

Object.assign()

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

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

Object.setPrototypeOf()

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

Object.getPrototypeOf()

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

Object.values()

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

Object.keys()

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

Object,entries()

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

Object.fromEntries()

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

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

  Object.fromEntries(new URLSearchParams('foo=bar&baz=qux'))
  // { foo: "bar", baz: "qux" }

Object.getOwnPropertyNames(obj)

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

Object.getOwnPropertySymbols(obj)

返回对象自有的Symbol属性,原型链上的属性不会被获取。返回值是存储自有Symbol属性的数组。

  let name = Symbol.for('name');
  let obj = {
    [name]: 'name',
  }
  Object.defineProperties(obj, {
    age: {
      value: 22,
      enumerable: false,
      writable: true
    },
    sex: {
      value: 'boy',
      enumerable: false,
      writable: true
    }
  })
  console.log(Object.getOwnPropertyNames(obj)); //  ["age", "sex"]
  console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(name)]

Object.preventExtensions(obj)

方法用于将一个对象设置为不可扩展,也就是不能再为其添加新的属性。

Object.isFrozen(obj)

方法用于判断一个对象是否已冻结。

Object.freeze(obj)

方法用于冻结一个对象。即将对象设置为不可扩展、将对象的所有自有的属性和方法(包括Symbol值的属性和方法)配置为不可配置、不可写。

Object.isSealed()

方法用于判断一个对象是否是已密封的状态。密封状态是指一个对象是不可扩展的,且所有自有属性和方法都是不可配置的。

Object.seal(obj)

方法用于密封一个对象,即将对象设置为不可扩展,同时将对象的所有自有属性都设置为不可配置(包括Symbol值的属性)。也就是说,不能给对象添加新的属性和方法,也不能删除现有的属性和方法、不能修改现有属性和方法的配置。但如果对象的属性和方法是可写的,那该属性和方法仍然可以修改。

Object.isExtensible(obj)

方法用于判断一个对象是否是可扩展的。

默认情况下,对象都是可以扩展的,即对象可以添加新的属性和方法。使用Object.preventExtensions()、Object.seal()和Object.freeze()方法都可以标记对象为不可扩展。

在ES5中,如果参数是非对象类型,会抛出TypeError异常。

在ES6中,如果参数是非对象类型,则会认为是一个不可扩展的普通对象,因此会返回false。

Object.preventExtensions()

方法用于将一个对象设置为不可扩展,也就是不能再为其添加新的属性。

对象默认是可扩展的,即可以添加新的属性。如果一个对象被配置为不可扩展,则无法添加新的属性,这是一个不可逆的操作。不可扩展的对象仍然可以删除已有的属性(取决于属性的可配置性),但如果尝试添加新的属性到不可扩展对象,会引发TypeError异常(严格模式)或静默失败。

Object.preventExtensions()仅阻止添加自身的属性。但属性仍然可以添加到对象原型,而这个不可扩展的对象同样会继承这些后来添加的原型对象的属性。