[Day21] 物件的基础概念2

今天来介绍如何判定物件与纯值以及关於物件未被定义的属性

物件与纯值

在 JavaScript 只有两种型别,纯质与物件,而 物件可以新增属性,纯值不能

物件

昨天 Day20 - 物件的基础概念 有提到可以透过物件实字来宣告物件,且可使用点记法、括号法来新增物件的属性

const family = {name: 'Carol'};
family.money = 200;
console.log(family); // {name: 'Carol', money: 200}

纯值

而所谓的 纯值 就是在 Day13 - JavaScript 的原始型别 所提到的 JavaScript 原始型别,分别有:

  • Number 数字型别
  • String 字串型别
  • Boolean 布林值
  • Null 空
  • Undefined 未定义
  • BigInt 整数数值
  • Symbol

纯值是无法新增属性的,可看以下范例:

在纯字串下新增属性,会发现没有改变

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 = 2b 其实是全域的属性而非变数,所以可被删除

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

参考文献

六角学院 - JavaScript 核心篇


<<:  Day 24 XIB跳转页面以及UIAlertController的练习(2/3)

>>:  大共享时代系列_020_共同工作空间(Coworking Space)

Day17 Mixin 後,搭配 RWD

大家好,我是乌木白,今天要和大家介绍 Mixin 和 RWD 搭配该如何使用? 原本 RWD 写法...

Day2 React是什麽呢?

React是由facebook推出的前端函式库 (library),主要使用语言是Javascrip...

< 关於 Next: 开始打地基| CSS的引入方式 >

09-17-2021 本章内容 添加样式-全域样式 添加样式-模组化样式 添加样式-Sass 添加样...

Transactions (1) - ACID

此系列是 资料工程师修炼之路 的後半部份,一样是 Design Data Intensive Ap...

#12 Web Crawler 5

今天应该是爬虫的最後一篇了。我们要把爬下来的资料做成「每日铁人赛热门 Top 10」。 来看看爬下来...