由於原語沒有屬性,並且foo.bar
中的值是原語。
當您訪問(獲取或設置)基元的屬性時,JavaScript引擎會爲該基元創建一個對象,設置或檢索屬性值(如果有),然後丟棄該對象。 (這就是爲什麼(42).toString()
作品;原始被提升爲由Number.prototype
支持對象,toString
從該對象檢索和調用this
參照對象,然後該對象被扔掉。)
所以,雖然對象是在您的foo.bar.baz = null
聲明中創建,其baz
屬性設置爲null
,該對象從未存儲在任何位置(當然不在foo.bar
),因此它被丟棄。稍後,當您執行if (foo.bar.baz === null)
時,會創建一個新的對象,該對象不具有該屬性,因此它的baz
屬性(因爲它沒有)會得到undefined
屬性。 (當然,JavaScript引擎可以優化這個過程以避免不必要的對象創建。)
我們可以在Number.prototype
上創建一個返回創建對象的函數,以演示每次訪問屬性時確實會發生對象創建在原始:
// Add a `nifty` method to numbers
Object.defineProperty(
Number.prototype,
"nifty",
{
value: function() {
console.log("Number#nifty called");
return this;
}
}
);
var n = 42; // A primitive number
console.log(typeof n); // "number"
var obj1 = n.nifty(); // Creates an object, which we keep
console.log(typeof obj1); // "object"
var obj2 = n.nifty(); // Do it again, and a new object is created
console.log(obj1 === obj2); // false, they're not the same object
如果你想設置的許多屬性和留住他們,你可以做到這一點明確創建Number
對象:
var n = new Number(42);
n.baz = null;
console.log(n.baz === null); // true
這是罕見想要做到這一點,但它是可能的。只是要注意,由於我們前面顯示,二Number
對象用相同的原始值不==
對方:
var n1 = new Number(42);
var n2 = new Number(42);
console.log(n1 == n2); // false
console.log(n1 === n2); // false
>
,<
,>=
和<=
將迫使數回到原語並使用原始值,但==
和===
不會。
'foo.bar'不能同時是一個數字和一個對象 – tkausl
@tkausl是正確的,而數字對象沒有baz屬性,所以你不能真的更新這個屬性。 –