對象的三個屬性
每個對象都擁有三個特性(屬性)(object attribute):
- 對象的原型(prototype)。指向另外一個對象,本對象的屬性繼承自它的原型對象。
- 對象的類(class)。是一個表示對象類型的字符串。
- 對象的擴展標記(extensible flag)。指明瞭(在ES5中)是否可以向該對象添加新屬性。
原型屬性
【01】對象的原型屬性是用來繼承屬性的。
【02】我們經常把“對象的原型屬性”直接叫做“對象的原型”。
【03】原型屬性是在對象創建之初就設置好的。
- 通過對象直接量創建的對象使用Object.prototype作爲它們的原型。
- 通過new創建的對象使用構造函數的prototype屬性作爲它們的原型。
- 通過Object.create()創建的對象使用第一個參數(也可以是null)作爲它們的原型。
【04】在ES5中,Object.getPrototypeOf(obj)可以查詢它的原型。
並不能直接通過對象實例.prototype屬性的形式訪問到對象的原型。
不能在對象實例的prototype上添加屬性和方法。
比如:
類屬性
【01】ES3和ES5都未提供設置這個屬性的方法,並只有一種間接的方法可以查詢它。
【02】要想獲得對象的類,可以調用對象的toString()方法,然後提取已返回字符串的第8個到倒數第二個位置之間的字符。
默認的toString()方法(繼承自Object.prototype)返回瞭如下這種格式的字符串:
[object class]
很多對象繼承的toString()方法重寫了,爲了能調用正確的toString()版本,必須間接地調用Function.call()方法。
【03】
- 通過內置構造函數(比如Array和Date)創建的對象包含“類屬性”(class attribute),它與構造函數名稱相匹配。(疑惑)
- 宿主對象也包含有意義的“類屬性”,但這和具體的JS實現有關。
- 對象的4種創建方式創建的對象的類屬性都是“Object”。
【04】classof()函數,可以返回任何類型任意對象的類:
function classof(o) {
if (o === null) return "Null";
if (o === undefined) return "Undefined";
return Object.prototype.toString.call(o).slice(8,-1);
}
數字、字符串和布爾值可以直接調用toString()方法,就和對象調用toString()方法一樣
這些類型的變量調用toString()方法,而不是通過它們的直接量調用toString(),比如1.toString()是不對的,而是要先聲明變量var a=1;然後調用a.toString()。
classof(null) // => "Null"
classof(1) // => "Number"
classof("") // => "String"
classof(false) // => "Boolean"
classof({}) // => "Object"
classof([]) // => "Array"
classof(/./) // => "Regexp"
classof(new Date()) // => "Date"
classof(window) // => "Window"(這是客戶端宿主對象)
function f() {}; // 定義一個自定義構造函數
classof(new f()); // => "Object"
可擴展性
【01】對象的可擴展性表示是否可以給對象添加新屬性。
可擴展屬性的目的是將對象“鎖定”,以避免外界的干擾。
【02】所有內置對象和自定義對象都是顯式可擴展的,除非將它們轉換爲不可擴展的,宿主對象(BOM,DOM)的可擴展性是由JS引擎定義的。
【03】如果給一個不可擴展的對象的原型添加屬性,這個不可擴展的對象同樣會繼承這些新屬性。
(zyx456:原型添加屬性,繼承原型的對象也自動獲取這些新屬性,即使該對象爲不可擴展性)