JavaScript系列之对象

148 阅读2分钟

对象的两种定义形式

文字语法:

var obj = {
  //...
}

构造形式:

var obj = new Object()
obj.key = value

对象的内容

对象内部一般存储的是属性的名称,它们就像指针(JavaScript理解成引用更合适),指向这些真正的存储位置。

在对象中, 属性名永远是字符串,其他值作为属性名会被转换为一个字符串。

访问属性的两种方法:

  1. .操作符
  2. []操作符
var myObject = { 
  a: 2
};

myObject.a; // 2
myObject["a"]; // 2

可计算属性名

我们一般通过.访问对象属性,但如果你想通过表达式来计算属性名,那就需要[]了

var prefix = "foo";
var myObject = {
  [prefix + "bar"]:"hello", 
  [prefix + "baz"]: "world"
};

myObject["foobar"]; // hello
myObject["foobaz"]; // world

复制对象

  1. JSON.parse(JSON.stringify(obj))

深拷贝,但对于null,undefined一些特殊情况不适用

  1. ES6的Object.assign()方法

浅拷贝,第一个参数是目标对象,之后还可以跟一个或多个源对象。

var newObj = Object.assign({}, obj)
  1. 递归实现深拷贝

属性描述符

从ES5开始,所有的属性都具备了属性描述符。

  1. writable:决定是否可以修改属性的值。
  2. configurable:决定属性是否可以配置。
  3. enumerable:决定属性是否可枚举。

我们可以使用Object.getOwnPropertyDescriptor()获取对象属性的描述符。 可以使用Object.defineProperty()修改属性描述符的值。

var myObject = { 
  a:2
};
Object.getOwnPropertyDescriptor( myObject, "a" );
// {
// value: 2,
// writable: true,
// enumerable: true,
// configurable: true 
// }

var myObject = {};
  Object.defineProperty( myObject, "a", {
      value: 2,
      writable: false, // 不可写! 
      configurable: true, 
      enumerable: true
     } 
  );

myObject.a = 3;
myObject.a; // 2

让对象不可变

  1. 结合writable: falseconfigurable: false 可以创建一个真正的常量属性(不可修改,从新定义或删除)
  var myObject = {};
     Object.defineProperty( myObject, "FAVORITE_NUMBER", {
         value: 42,
        writable: false,
        configurable: false 
      } 
  );
  1. 禁止扩展 如果你想禁止一个对象添加新属性并且保留已有的属性,可以使用Object.preventExtensions()
var myObject = { 
  a:2
};
Object.preventExtensions( myObject );
myObject.b = 3;
myObject.b; // undefined
  1. 密封Object.seal()
  2. 冻结Object.freeze()

Getter和Setter

对象默认的[[Put]]和[[Get]]操作分别可以控制属性值的设置和获取。

getter和setter都是隐藏函数,会在获取属性值和设置属性值时自动调用。

var myObject = {
// 给 a 定义一个 getter 
  get a() {
    return 2; 
  }
};
Object.defineProperty( myObject, // 目标对象 
      "b", // 属性名
  {
  // 描述符
  // 给 b 设置一个 getter
    get: function(){ 
      return this.a * 2 
    },
    // 确保 b 会出现在对象的属性列表中
    enumerable: true
  }
);

myObject.a; // 2
myObject.b; // 4

这两种定义方法都会在对象中创建一个不包含值的属性,对于这个属性的访问会自动调用一个隐藏函数,它的返回值会被当做属性访问的返回值。

判断对象属性是否存在

  1. obj.hasOwnProperty()只检查当前对象是否存在该属性,不看原型链。
  2. in操作符会查看原型链。

对象遍历

for...in可以用来遍历对象的可枚举属性列表(包括原型链)。