理解JavaScript对象的属性

239 阅读3分钟

一、对象的定义

对象为一组属性(和方法)的无序集合。

  let person = {
    name: "zs",
    age: 21,
    sayName() {
      console.log(this.name);
    }};

这个例子创建了一个名为person的对象,它具有两个属性(name、age),以及一个方法(sayname())。

二、对象的属性

属性分为两种:数据属性和访问器属性。用来描述属性的特征的叫内部特性,内部特性一般用两个中括号括起来,如: [[Enumerable]] (可枚举性)。

1、数据属性

数据属性包含数据值。数据属性有四个特性:

  1. [[Configurable]]:可配置性,表示属性是否可以通过delete删除并重新定义,默认true。
  2. [[Enumerable]]:可枚举性,表示属性是否可以通过for-in循环返回,默认true。
  3. [[Writable]]:表示属性是否可以被修改,默认true。
  4. [[Value]]:表示属性实际的值,默认值为undefined。

2、访问器属性

访问器属性不包含数据值,他们包含一个获取(getter)函数和一个设置(setter)函数,这两个函数也并不是必须的。访问器属性有四个特性:

  1. [[Configurable]]:可配置性,表示属性是否可以通过delete删除并重新定义,默认true。
  2. [[Enumerable]]:可枚举性,表示属性是否可以通过for-in循环返回,默认true。
  3. [[Get]]:获取函数,读取属性时调用,会返回一个值,默认值为undefined。
  4. [[Set]]:设置函数,写入属性时调用并传入新值,默认值为undefined。

访问器属性使用场景:设置一个对象的属性值,会导致一些其它变化发生。如果想要定义一个访问器属性,不能直接定义,必须采用Object.defineProperty(),如将下列book例子中的属性year定义为访问器属性:

let book={
  year_:2017,  //year_中的下划线常用来表示该属性不希望在对象方法的外部访问
  edition:1
};
Object.defineProperty(book,"year",{
  get(){
    return this.year_;
  },
  set(){
    if(setValue>2017){
      this.year_=newValue;
      this.edition+=setValue-2017;
    }
  }
})
book.year=2018;
console.log(book.edition); //2

3、合并对象

合并,即将源对象的属性复制给目标对象。ES6为合并对象提供了Object.assign()方法,这个方法接受一个目标对象,和一个或多个源对象。

let dest,src,res;
dest={};
src={name:'zs'};
res=Object.assign(dest,src);
console.log(dest===res);     //true(从一个对象到另一个对象的复制操作,复制的值其实是一个指针,它指向堆内存中的对象,因此两个变量都指向同一个对象。)
console.log(dest!==src);     //true

获取函数和设置函数无法进行合并操作,即使赋了,也只是一个静态值。 若需要合并的多个源对象中有相同的属性,则后面的属性值会覆盖前面的。

4、ES6操作定义对象的新增语法糖

1、属性名和变量名一样时,可简写,只写变量名。

let name='zs';
let person={
  name                    //只写变量名,自动被解释为使用同名属性键;等同于name:name。
}
console.log(person.name)  //{name:'zs'}

2、属性值可计算

要想使用变量来作为属性值,可以使用中括号语法来添加属性。

  const name = "name";
  const age = "age";
  let uniqueToken = 0;
  function getUniqueKey(key) {
    return `${key}_${uniqueToken++}`;   //模板字符串中可采用${}进行字符串插值,即可插入一个变量
  }
  let person = {
    [getUniqueKey(name)]: "zs",      //这里的[]包围的属性键,在运行时将作为表达式而不是字符串来处理
    [getUniqueKey(age)]: 21
  };
  console.log(person);         //{ name_0: 'zs' , age_1: 21 }

3、对象中的方法名可简写

let person = {
    sayName(){             //原本应写为:sayName:function(){  }
        console.log('zs');
    }
  }