1. 程式人生 > >深入理解javascript物件系列第一篇——初識物件

深入理解javascript物件系列第一篇——初識物件

前面的話

  javascript中的難點是函式、物件和繼承,前面已經介紹過函式系列。從本系列開始介紹物件部分,本文是該系列的第一篇——初識物件

物件定義

  javascript的基本資料型別包括undefinednullbooleanstringnumber和object。物件和其他基本型別值不同的是,物件是一種複合值:它將許多值(原始值或者其他物件)聚合在一起,可通過名字訪問這些值

  於是,物件也可看做是屬性的無序集合,每個屬性都是一個名值對。屬性名是字串,因此我們可以把物件看成是從字串到值的對映

  關於複合值和原始值的詳細區別移步至此

物件建立

  有以下三種方式來建立物件,包括new建構函式、物件直接量和Object.create()函式

【1】new建構函式

  使用new操作符後跟Object建構函式用以初始化一個新建立的物件

var person = new Object();
//如果不給建構函式傳遞引數可以不加括號 var person = new Object;
person.name = 'bai';
person.age = 29;
//建立無屬性的空物件
var cody1 = new Object();
var cody2 = new Object(undefined);
var cody3 = new Object(null);
console.log(typeof cody1,typeof
cody2, typeof cody3);//object object object

  如果該引數是一個物件,則直接返回這個物件 

var o1 = {a: 1};
var o2 = new Object(o1);
console.log(o1 === o2);// true

var f1 = function(){};
var f2 = new Object(f1);
console.log(f1 === f2);// true

  如果是一個原始型別的值,則返回該值對應的包裝物件

//String {0: "f", 1: "o", 2: "o", length: 3, [[PrimitiveValue]]: "foo"}
console.log(new Object('foo')); //Number {[[PrimitiveValue]]: 1} console.log(new Object(1)); //Boolean {[[PrimitiveValue]]: true} console.log(new Object(true));

  若Object()函式不通過new而直接使用,則相當於轉換方法,可以把任意值轉換為物件

  [注意]undefined和null會轉換為一個空物件

var uObj = Object(undefined);
var nObj = Object(null);
console.log(Object.keys(uObj));//[]
console.log(Object.keys(nObj));//[]

  如果Object()的引數是一個物件,則直接返回原物件

var o = {a:1};
var oObj = Object(o);
console.log(Object.keys(oObj));//['a']

  利用這一點,可以寫一個判斷變數是否為物件的函式

function isObject(value) {
  return value === Object(value);
}
isObject([]) // true
isObject(true) // false

【2】物件字面量

  javascript提供了叫做字面量的快捷方式,用於建立大多數原生物件值。使用字面量只是隱藏了與使用new操作符相同的基本過程,於是也可以叫做語法糖

  物件字面量是由若干名值對組成的對映表,名值對中間用冒號分隔,整個對映表用花括號括起來

  不同屬性之間用逗號分隔,屬性名可以是任意字串,屬性值可以是任意型別表示式,表示式的值是屬性值

//等價於var person = new Object();
var person = {}; 
var person = {
    name : 'bai',
    age : 29,
    5 : true
};

  使用物件字面量的方法來定義物件,屬性名會自動轉換成字串

//同上
var person = {
    'name' : 'bai',
    'age' : 29,
    '5' : true
}; 

  [注意]一般地,物件字面量的最後一個屬性後的逗號將忽略,但在IE7-瀏覽器中導致錯誤

//IE7-瀏覽器中報錯 SCRIPT1028: 缺少識別符號、字串或數字
var person = {
    name : 'bai',
    age : 29,
    5 : true,
};

【3】Object.create()

  ES5定義了一個名為Object.create()的方法,它建立一個新物件,第一個引數就是這個物件的原型,第二個可選引數用以對物件的屬性進行進一步描述

var o1 = Object.create({x:1,y:1}); //o1繼承了屬性x和y
console.log(o1.x);//1

  可以通過傳入引數null來建立一個沒有原型的新物件,但通過這種方式建立的物件不會繼承任何東西,甚至不包括基礎方法。比如toString()valueOf()

var o2 = Object.create(null); // o2不繼承任何屬性和方法
var o1 = {};
console.log(Number(o1));//NaN
console.log(Number(o2));//Uncaught TypeError: Cannot convert object to primitive value

  如果想建立一個普通的空物件(比如通過{}或new Object()建立的物件),需要傳入Object.prototype

var o3 = Object.create(Object.prototype); // o3和{}和new Object()一樣
var o1 = {};
console.log(Number(o1));//NaN
console.log(Number(o3));//NaN

   Object.create()方法的第二個引數是屬性描述符

var o1 = Object.create({z:3},{
  x:{value:1,writable: false,enumerable:true,configurable:true},
  y:{value:2,writable: false,enumerable:true,configurable:true}
}); 
console.log(o1.x,o1.y,o1.z);//1 2 3

物件組成

  物件是屬性的無序集合,由鍵名和屬性值組成

【鍵名】

  物件的所有鍵名都是字串,所以加不加引號都可以,如果不是字串也會自動轉換成字串

var o = {
  'p': 'Hello World'
};
var o = {
  p: 'Hello World'
};
var o ={
  1: 'a',
  3.2: 'b',
  1e2: true,
  1e-2: true,
  .234: true,
  0xFF: true,
};
//Object {1: "a", 100: true, 255: true, 3.2: "b", 0.01: true, 0.234: true}
o;

  [注意]如果鍵名不符合識別符號命名規則,則必須加上引號,否則會報錯

//Uncaught SyntaxError: Unexpected identifier
var o = {
    1p: 123
}

var o = {
    '1p': 123
}

【屬性值】

  屬性值可以是任何型別的表示式,最終表示式的結果就是屬性值的結果

var o ={
    a: 1+2
}
console.log(o.a);//3

  如果屬性值為函式,則通常把這個屬性稱為“方法”

var o = {
  p: function (x) {
    return 2 * x;
  }
};
o.p(1);//2

  由於物件的方法就是函式,因此也有name屬性。方法的name屬性返回緊跟在function關鍵字後面的函式名。如果是匿名函式,ES5環境會返回undefined,ES6環境會返回方法名

var obj = {
  m1: function f() {},
  m2: function () {}
};
obj.m1.name // "f"
obj.m2.name //ES5: undefined
obj.m2.name //ES6: "m2"

引用物件

  如果不同的變數名指向同一個物件,那麼它們都是這個物件的引用,也就是說指向同一個記憶體地址。修改其中一個變數,會影響到其他所有變數

var o1 = {};
var o2 = o1;

o1.a = 1;
console.log(o2.a);// 1
o2.b = 2;
console.log(o1.b);// 2

  如果取消某一個變數對於原物件的引用,不會影響到另一個變數

var o1 = {};
var o2 = o1;

o1 = 1;
console.log(o2);//{}

例項方法

valueOf()

  valueOf()方法返回當前物件

var o = new Object();
o.valueOf() === o // true

toString()

  toString()方法返回當前物件對應的字串形式

var o1 = new Object();
o1.toString() // "[object Object]"

var o2 = {a:1};
o2.toString() // "[object Object]"

  一般地,使用Object.prototype.toString()來獲取物件的類屬性,進行型別識別,詳細情況移步至此

toLocaleString()

  toLocaleString()方法並不做任何本地化自身的操作,它僅呼叫toString()方法並返回對應值

  [注意]DateNumber類對toLocaleString()方法做了本地化定製

var o = {a:1};
o.toLocaleString() // "[object Object]"

判斷為空

  判斷物件是否為空,有以下三種方法

  1、for-in語句

let isEmpty = (obj) => {
  for(let i in obj){
    return false
  }
  return true
}
console.log(isEmpty({}))//true
console.log(isEmpty({a:1}))//false

  2、JSON.stringify方法

let isEmpty = (obj) => {
  return JSON.stringify(obj) === '{}'
}
console.log(isEmpty({}))//true
console.log(isEmpty({a:1}))//false

  3、Object.keys方法

let isEmpty = (obj) => {
  return !Object.keys(obj).length
}
console.log(isEmpty({}))//true
console.log(isEmpty({a:1}))//false

參考資料

【1】 W3School-Javascript高階教程——引用型別 http://www.w3school.com.cn/js/pro_js_referencetypes.asp
【2】 阮一峰Javascript標準參考教程——物件 http://javascript.ruanyifeng.com/grammar/object.html
【3】《javascript權威指南(第6版)》第6章 物件
【4】《javascript高階程式設計(第3版)》第5章 引用型別
【5】《javascript語句精粹》第3章 物件
【6】《javascript面向物件精要》 第3章 理解物件
【7】《你不知道的javascript上卷》第3章 物件