《你不知道的JavaScript》整理(三)——对象


一、语法

两种形式定义:文字形式和构造形式。

//文字形式
var myObj = {
  key: value
};
//构造形式
var myObj = new Object();
myObj.key = value;

 

二、类型

对象是JavaScript的基础。

1)基本类型

在JavaScript中一共有六种主要类型(术语是“语言类型”):

string、number、booleannull、undefined、object

 

2)内置对象

JavaScript中还有一些对象子类型,通常被称为内置对象。

String、Number、Boolean、Object、Function、Array、Date、RegExp、Error

引擎可以将一些基础类型自动转换成相应的内置对象,然后就能调用对象的属性或方法。

//将字符串转换为String对象
var strPrimitive = "I am a string";
console.log( strPrimitive.length ); // 13
console.log( strPrimitive.charAt( 3 ) ); // "m"

//将数字转换为Number对象
var num = 42.359.toFixed(2);
console.log(num);//42.36

 

三、内容

1)属性

var myObject = {
 a: 2
}; 
myObject.a; // 2 属性访问
myObject["a"]; // 2 键访问

.a语法通常被称为“属性访问”,["a"]语法通常被称为“键访问”。

 

2)复制对象

对于JSON安全(也就是说可以被序列化为一个JSON字符串并且可以根据这个字符串解析出一个结构和值完全一样的对象)的对象来说,有一种巧妙的复制方法:

var newObj = JSON.parse( JSON.stringify( someObj ) );

相比深复制,浅复制非常易懂并且问题要少得多,所以ES6定义了Object.assign(..)方法来实现浅复制。

3)属性描述符

从ES5开始,所有的属性都具备了属性描述符。可通过方法Object.defineProperty()实现。

var myObject = {};

Object.defineProperty(myObject, "a", {
  value: 2,
  writable: true,
  configurable: true,
  enumerable: true

});

console.log(myObject.a); // 2

Vue.js就是通过这个方法来实现追踪变化。

 

4)Getter和Setter

在ES5中可以使用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
  }
);

console.log(myObject.a); // 2
console.log(myObject.b); // 4

 

5)存在性

in操作符会检查属性是否在对象及其[[Prototype]]原型链中。

hasOwnProperty(..)只会检查属性是否在myObject对象中,不会检查[[Prototype]]链。

前面有一篇《JavaScript中typeof、toString、instanceof、constructor与in》做了些比较。

var myObject = {
  a: 2
};

("a" in myObject); // true
("b" in myObject); // false 

myObject.hasOwnProperty("a"); // true
myObject.hasOwnProperty("b"); // false

 

四、遍历

和数组不同,普通的对象没有内置的@@iterator,所以无法自动完成for..of遍历。

但你可以给任何想遍历的对象定义@@iterator。

var myObject = {
  a: 2,
  b: 3
};

Object.defineProperty(myObject, Symbol.iterator, {
  enumerable: false,
  writable: false,
  configurable: true,
  value: function() {
    var o = this;
    var idx = 0;
    var ks = Object.keys(o);
    return {
      next: function() {
        return {
          value: o[ks[idx++]],
          done: (idx > ks.length)
        };
      }
    };
  }
});

// 手动遍历 myObject
var it = myObject[Symbol.iterator]();
it.next(); //{ value:2, done:false }
it.next(); //{ value:3, done:false }
it.next(); //{ value:undefined, done:true }

// 用 for..of 遍历 myObject 
for (var v of myObject) {
  console.log(v);
}
// 2 
// 3