1. 程式人生 > >JavaScript 對象(上)

JavaScript 對象(上)

字符 undefined javascrip typeof date() 字符串 空字符 type UNC

簡述:

  1、是 JavaScript 的基本類型

  2、是一種復合值,可通過名字訪問這些值

  3、可看作屬性的無序集合,每個屬性都是一個名/值對(屬性名是字符串或標識符

  4、可以從一個稱為原型的對象繼承屬性(核心特征)

  5、是動態的,可新增或刪除屬性,操作對象是通過引用而不是值

  6、屬性名可以是包含空字符在內的任意字符串,但對象中不能存在兩個或多個同名屬性;非嚴格模式下允許,但後者會覆蓋前者的值

註:除了字符串、數字、true、false、null 和 undefined 之外,JavaScript 中的值都是對象

原型:

  1、大部分 JavaScript 對象都和另一個對象(原型)相關聯,每個對象都從原型繼承

屬性

  2、可以通過 JavaScript 代碼 Object.prototype 獲得對其原型對象的引用

  3、所有通過對象直接量創建的對象都具有同一個原型對象,使用相同構造函數的對象也具有同一個原型對象

  4、所有的內置構造函數(以及大部分自定義的構造函數)都具有一個繼承自 Object.prototype 的原型

  5、一個普通對象的原型可能也有原型,而這一系列鏈接的原型對象就是”原型鏈

創建對象:

  1、對象直接量:由若幹名/值對組成的映射表,名/值對中間用冒號分隔,名/值對之間用逗號分隔,整個映射表用花括號括起來

// 對象裏面的屬性值可以是對象
let obj = {"name": "Yam", "other": {"weight": "yyy", "high": "xxx"}, "age": 200}; console.log(obj["other"]["high"]); // 輸出 xxx
console.log(obj.other.high);

註:對象直接量是一個表達式,這個表達式的每次運算都創建並初始化一個新的對象

  2、關鍵字 new:關鍵字後跟隨一個函數(構造函數)調用,用以初始化一個新創建的對象

let arr = new Array();    // 創建一個空數組
let date = new Date();    //
創建一個表示當前時間的 Date 對象

  3、Object.create(proto [, more]):創建一個新對象,第一個參數為這個對象的原型,第二個參數可對對象的屬性進行進一步描述

// ES5 定義的
let obj = Object.create({"x": 1, "y": 2});
console.log(obj.x);  // 輸出 1

屬性查詢和設置:

// inherit 函數來自 JavaScript 權威指南

function inherit(p) {
    if (p == null)
        throw TypeError();
    if (Object.create)
        return Object.create(p);
    let t = typeof p;
    if (t != "object" && t != "function")
        throw TypeError();
    function f() {};    // 定義一個空構造函數
    f.prototype = p;
    return new f(); // 使用 f() 創建 p 的繼承對象
}

let o = {};
o.x = 1;
let p = inherit(o);
p.y = 2;
// 屬性賦值操作首先會檢查原型鏈,以此判斷是否允許賦值
// 賦值時也只是在原始對象上創建屬性或對已有屬性賦值,而不會修改原型鏈
// 屬性賦值要麽失敗,要麽創建一個屬性,要麽在原始對象中設置屬性
p.x = 3;
console.log(o.x);   // 輸出 1
// 屬性訪問可以通過點或方括號來操作
console.log(p["x"] + p.y);  // 輸出 5

// 非嚴格模式下查詢一個不存在的屬性並不會報錯
console.log(p.z);   
// 但如果對象本身不存在,那麽查詢這個不存在的對象的屬性就會報錯(undefined、null)
// console.log(p.z.i);    // 報錯

註: 1、不能給只讀屬性重新賦值

   2、不能通過同名自有屬性覆蓋只讀的繼承屬性

   3、如果對象 obj 不可擴展,那麽不能在 obj 中定義新屬性

刪除屬性:

  1、delete 運算符可以刪除對象的屬性,但只是斷開屬性和宿主對象的聯系,而不會去操作屬性中的屬性

  2、delete 運算符只能刪除自有屬性,而不能刪除繼承屬性

  3、delete 刪除成功或者沒有任何副作用時,它返回 true;若它後面不是一個屬性訪問表達式,同樣會返回 true!!!

  4、不能刪除那些可配置性為 false 的屬性,但可以刪除不可擴展對象的可配置屬性,非嚴格模式下返回 false,嚴格模式報錯

let par = {"q": 10};
let a = Object.create(par);
a.p = {"x": 1};
let b = a.p;
delete a.p; // delete 只斷開屬性和宿主對象的聯系,而不會去操作屬性中的屬性,可能會造成內存泄漏
console.log(b.x);   // 輸出 1

console.log(delete a.q);    // 什麽也沒做,輸出 true
console.log(a.q);   // 輸出 10
console.log(delete a.t);    // 輸出 true
console.log(delete 20); // 輸出 true

console.log(delete Object.prototype);   // 輸出 false
console.log(delete b);  // 刪除一個通過變量聲明或函數聲明(var 和 let)的對象會返回 false

檢測屬性:

  1、運算符 in:左側為屬性名,右側為對象,若對象的自有屬性或繼承屬性中包含這個屬性,則返回 true

  2、hasOwnProperty() 方法:檢測給定屬性是不是對象的自有屬性

  3、propertyIsEnumerable() 方法:檢測屬性是不是自有屬性且可枚舉

// 若對象的自有屬性或繼承屬性中包含這個屬性,則返回 true
let ino = {"x": 1};
console.log("x" in ino);    // true
console.log("toString" in ino); // true
console.log("y" in ino);    // false

// 檢測給定屬性是不是對象的自有屬性
console.log(ino.hasOwnProperty("toString"));    // false

// 檢測屬性是不是自有屬性且可枚舉
console.log(ino.propertyIsEnumerable("x")); // true
console.log(Object.prototype.propertyIsEnumerable("toString"));  // 不可枚舉,false

註:可以使用 "attr !== undefined;" 來判斷屬性是否存在,但若屬性存在且值為 undefined,則只能使用 in

枚舉屬性:

  1、for/in 循環可以在循環體中遍歷對象中所有可枚舉的屬性(包括自有屬性和繼承屬性),並把屬性名賦值給循環變量

  2、ES5 定義了 Object.keys(),它返回一個由對象中可枚舉的自有屬性的名稱組成的數組

  3、ES5 定義了 Object.getOwnPropertyNames(),它返回對象的所有自有屬性的名稱,而不僅僅是可枚舉屬性

let foro = {"x": 1, "y": 2};
for (let temp in foro)
    console.log(temp);  // 輸出 x y
console.log(Object.keys(foro)); // 輸出 [‘x‘, ‘y‘]
console.log(Object.getOwnPropertyNames(Object.prototype));

JavaScript 對象(上)