iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 6
0

物件是特性(property,具有名稱和值,name:value pairs)的無序集合。

原型(prototypes)

每個JavaScript物件都有第二個JavaScript物件(prototype),第一個物件即是從prototype繼承特性

var ary = new Array(1,2,3)
  • Array.prototype繼承了Objcet.prototype特性。new Array() 創建了一個array物件,同時繼承了Array.prototype和Object.protorype兩者的特性。

用New Array()創建物件,其原型是Array.prototype
除了Object.protorype沒有原型物件外(無繼承任何特性),其他原型物件(prototype)都具有原型的正常物件。所有內建的建構式(constructor)都有個繼承Object.prototype的原型。

  • Object.create(obj) 一個繼承obj原型的物件
function inherit(p){
    if(p == null) throw TypeError();
    if(Object.create) return Object.create(p); // Objcet.creat是ES5的語法
    var t = typeof p;
    if(t !== "Object" && t !== "function") throw TypeError();
    function f(){}
    f.protorype = p;
    return new f();
}
//-----------
var obj={ x:"dont change this value"};
lib_function(inherit(obj)); // 防止對obj的修改

繼承

JavaScript物件有一組自有特性(own properties),同時也從原型物件繼承了一組特性。

var obj_1 = {x:5};
var obj_2 = Object.create(obj_1);
obj_2.y = 9;
obj_2.x;  // return 5

  • 可以從obj_2看出,它繼承了obj_1且obj_1繼承了Object。所以obj_2同時繼承了obj_1與Objcet。
  • obj_2.x 會先去找自有特性,找不到會往原型找,一層一層往下找。
  • property在指定的時候,會檢視原型鍊(properties chain)
    • 執行obj_2.x = 3,
      • 若所繼承的obj_1裡的x是唯讀的話,那這個指定會失敗。
      • 若非唯讀,會在原本的物件新建或設定property,永遠不修改到原型鍊的property

以下例子可以看出
obj_2 在指定x=8並沒有修改到原本的物件,而是在自己的物件新增一個property。

特性存取錯誤

  • 當取用不存在的property並不會throw error,會return undefined。
  • 當取用不存在的Objcet會throw error。
var book ={};
book.title; // return undefined
book.title.length // thorw TypeError

為什麼book.title.length會throw TypeError,但book.title卻return undefined ?
因為當執行book.title是在取property,因為title未初始化,所以return undefined。
當執行book.title.length,會先去取title物件然後再取length property,所以在取title物件時,因為沒有這物件所以會throw TypeError。

  • 慣用的判斷技巧
    var len = book && book.title && book.title.length;
    • 僅會回傳book.title.length或undefined,當AND運算式(&&)左邊成立則會回傳右邊的值,可參考Day4 AND 運算式。
  • 若嘗試在null or undefined存取值,會throw TypeError。

測試property

var obj ={x:5}; 來做解釋

  • in 運算子

    var obj ={x:5};
    "x" in obj; // return true
    "y" in obj; // return false
    "toString" in obj; //return true
    

    判斷property是否存在可判斷是否為undefined即可,並非一定要用in。
    obj.y !== undefined

    • 當property值是undefined那就一定要用in來判斷
    var obj={x: undefined};
    obj.x !== undefine; //return false;property存在但值為undefined
    "x" in obj; // return true
    

    在上面這情況下判斷"x" property是否存在於obj,用in判斷比較合理。

  • hasOwnProperty(): 僅測試自身擁有的property,不會往原型鍊找。

    var obj ={x:5};
    obj.hasOwnProperty("x"); // return true
    obj.hasOwnProperty("y"); // return false
    obj.hasOwnProperty("toString"); // return false
    
  • porpertyIsEnumerable(): 更完善的hasOwnProperty(),判斷自有的property且是enumerable

    var obj= {x:5};
    var objA= Object.create(obj);
    objA.y= 9;
    objA.porpertyIsEnumerable("x") // return false,非自有property
    objA.porpertyIsEnumerable("y") // return true,自有property
    
    Objcet.property.porpertyIsEnumerable("toString") // return false,自有property但非enumerable
    
  • 列出property有兩個函式

    1. Objcet.keys() // 回傳可列舉自有property
    2. Object.getOwnPropertyNames()// 回傳全部(不管是否可列舉)自有property。

Getters / Setters (accessor)

  • object裡面key-value pair的value可用getter與setter取代。

  • 當property 只有setter時,代表只有寫入特性(如嘗試著取值得會得到undefined)。

  • 當property 只有getter時,代表只有讀取特性。

  • 當property有setter與getter時,代表有讀寫特性。

    var obj ={
        x:3,
        y:3,
        set r(v){ 
            this.x=v;
            this.y=v;
            },
        get r(){
            return this.x * this.y;
        }
    }
    // -----
    var p = Object.create(obj);
    p.r = 5;
    

特性屬性(property attributes)

在資料特性有四個屬性分別是value、writable、enumerable、configurable。
在accessor(getter/setter)特性沒有value(運用了get取代了)、writable(取決於有沒有setter),所以包含的屬性有get、set、enumerable、configurable。

var obj={}

Object.defineProperty(obj,"x",{ value:5,
                                wirtable: true,
                                enumerable: false,
                                configurable: true
                              })

obj.x; //return 5
obj.keys(); //return [] , 因為enumerable:false

// 修改為writable:false
Object.defineProperty(obj,"x",{ wirtable:false  }); 
obj.x = 9; // 無聲無息的錯誤,在strict下會throw TypeError

// 因為configurable:true,所以可以用配置的方式給值
Object.defineProperty(obj,"x",{ value:9  }); 
obj.x; //return 9

// 改為accessor特性
Object.defineProperty(obj,"x",{ get: function(){return 1;} }); 
obj.x; //return 1
  • 新創建obj時value、wirtable、enumerable、configurable有省略的部分會以false or undefined取代。但若是以創立只修改某些屬性沒修改的部分不會更動

序列化物件

  • JSON.stringify
  • JSON.parse

上一篇
Day 5: 述句(Statements)
下一篇
Day 7: 陣列 Array
系列文
Javascript 犀牛本-濃縮再濃縮 提煉再提煉30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言