今天來介紹如何判定物件與純值以及關於物件未被定義的屬性
在 JavaScript 只有兩種型別,純質與物件,而 物件可以新增屬性,純值不能
昨天 Day20 - 物件的基礎概念 有提到可以透過物件實字來宣告物件,且可使用點記法、括號法來新增物件的屬性
const family = {name: 'Carol'};
family.money = 200;
console.log(family); // {name: 'Carol', money: 200}
而所謂的 純值
就是在 Day13 - JavaScript 的原始型別 所提到的 JavaScript 原始型別,分別有:
純值是無法新增屬性的,可看以下範例:
在純字串下新增屬性,會發現沒有改變
const nickName = 'Carol';
nickName.money = 200;
console.log(nickName); // Carol
另外使用建構式所新增的字串並非純值,我們可以使用是否可新增屬性來判定,利用 typeof
也可得出 object
的結果
以下範例中,使用 new String()
建構式所得出的字串並不能新增屬性,所以它並不是純值
const nickName = new String('Carol');
console.log(typeof nickName); // object
console.log(nickName); // String {'Carol'}
nickName.money = 200;
console.log(nickName); // String {'Carol', money: 200}
陣列是物件型別,所以可以新增屬性
const array = [];
array.a = 1;
console.log(typeof array); // object
console.log(array); // [a: 1]
雖然使用 typeof
檢驗函式的型別,會得出 function
結果,但函式是屬於物件型別下的子型別,也是物件型別,只是比物件多了被呼叫的能力
在以下範例中,可看到函式可以新增屬性:
使用
console.dir()
,可看到函式的物件格式,且可被展開
function fn() {
console.log('Carol');
}
fn.a = 1;
console.log(typeof fn); // function
console.dir(fn); // ƒ fn()
要注意的是: 函式的屬性 name
為函式本身名稱,不可被覆蓋
以下範例中,可看到使用 fn.name = '123'
並無法更改函式的 name
屬性,因 name
是函式本身名稱所以無法被覆蓋,fn.a = 1
則因函式是物件所以可以被新增
function fn() {
console.log('Carol');
}
fn.a = 1;
fn.name = '123';
console.dir(fn);
當查看 未被定義的物件屬性,會顯示 undefined
而非 is not defined
,且未被定義的物件屬性也無法再新增屬性
以下範例中,可以看到物件下未定義的屬性值是 undefined
,且因這個屬性 members
不存在所以也無法在 members
下新增屬性 mom
,故顯示錯誤訊息 Uncaught TypeError: Cannot set properties of undefined (setting 'mom')
const family = {
name: 'Carol'
}
console.log(family); // {name: 'Carol'}
console.log(family.members); // undefined
family.members.mom = 'aa';
console.log(family); // 報錯 - Uncaught TypeError: Cannot set properties of undefined (setting 'mom')
直接定義屬性,先給予一個預設值
直接屬性 members
,先給予一個空物件,最後再覆蓋
const family = {
name: 'Carol',
members: {}
}
family.members.mom = 'aa';
console.log(family); // {name: 'Carol', mom: {name: 'aa'}}
直接在未定義屬性下新增一個物件結構
雖然屬性 members
未被定義,但可直接在 members
下新增一個物件結構
const family = {
name: 'Carol'
}
family.members = {
mom = 'aa'
};
console.log(family); // {name: 'Carol', mom: {name: 'aa'}}
昨天 Day20 - 物件的基礎概念 有提到以下範例,b = 2
的 b
其實是全域的屬性而非變數,所以可被刪除
var a = 3;
b = 2;
console.log(delete a); // false
console.log(delete b); // true
結合今天所講的內容,以下範例中 a
並非變數且未被定義,而要查看全域中不存在的屬性,使用 console.log(全域屬性);
會報錯,而未被定義的物件屬性值為 undefined
,所以可改用 console.log(window.全域屬性);
得出值為 undefined
// a 為未被定義的全域屬性
console.log(a); // Uncaught ReferenceError: a is not defined
可改為
console.log(window.a); // undefined