JavaScript Day 18. 原始型别与物件型别

JavaScript 日常系列写着写着,就此进入了我的苦手范围QQ,之後的主题应该都是我的修罗场,考验着自己观念有没有打稳的每一篇;不过,我还是会加油的。

在写这篇之前我看了许多文章,趁着记忆还新,赶紧把自己理解的部分写下来。

前面几篇我们有稍微谈到型别,大概是小小擦个边这样子谈到,但其实那些我们点名出来的型别都包含在 JavaScript 的两大型别里面,分别是「原始型别」与「物件型别」。


原始型别 ( Primitive Type)

原始型别为 Pass by value,是一个分配好的记忆体空间,他是固定的,我们无法去更动他的记忆体位置。

另一个名字为基本型别,还叫做「纯值」;白话一点来说,他代表的是一个单一的值,并且没有「方法」也不能被改变,譬如 let a = 3 的那个 3,他就是「3」而已不会变动也没有其他意思。

在这个归类下的型别有几种:

  • 布林 ( Boolean )
  • Null ( 空 )
  • Undefined ( 未定义 )
  • Number ( 数值 )
  • String ( 字串 )
  • BigInt ( 整体数值 )
  • Symbol ( ES6新定义的型别 )

辨别原始型别

那麽要如何知道是否为原始型别呢?我们可以使用 typeof 去检查,这边要注意除了 null 以外,其他型别都是有办法正确检测的。

let newString = '福尔摩斯';
typeof newString; // "string"
typeof '福尔摩斯'; // "string"

let newNumber = 2018;
typeof newNumber; // "number"
typeof 2018; // "number"

let newBoolean = true;
typeof newBoolean; // "boolean"
typeof true; // "boolean"

let newUndefined = true;
typeof newUndefined; // "undefined"
typeof undefined; // "undefined"

let newNull = true;
typeof newNull; // "object"
typeof null; // "object"

null 这个部分呈现 typeof null === "object" 其实是 JavaScript 早期的一个 bug,null 应该要是 null 才对。


物件型别 ( Object Type )

物件型别针对记忆体位置去操作,是 Pass by reference,当我们将一个物件赋值给变数,他会参照那个物件的记体位置。

辨识出原始型别以後,剩下的几乎都是物件型别了,譬如我们所熟悉的「阵列」与「函式」,甚至到全域本身都是物件型别的类别。

有什麽证据证明阵列是物件呢?让 typeof 来证明:

let arr = []  
console.log(typeof arr)  //object

另外,这边也提供一个分辨阵列的方法 Array.isArray(),使用这个方法会让函式检查传入的值是否为一个阵列。

语法:

Array.isArray(obj)

以下提供范例:

Array.isArray([1, 2, 3]);  // true
Array.isArray({foo: 123}); // false
Array.isArray('foobar');   // false
Array.isArray(undefined);  // false

再把话题拉回来,刚刚说到函式也是物件型别,可是当我们对函式使用 typeof 的时候会惊讶的发现,回传的竟然不是 object

let name = function(){
	console.log('Agnes') 
} 
console.log(typeof name) // function

前几篇我有介绍到一个牵涉到原型的方法 instanceof,在这边刚好就可以使用他来帮我们判断 function 到底是不是 object。

console.log( name instanceof Object ) // true

可以看到函式确实是物件型别没错,但为什麽会回传 function 呢?typeof 回传 function 的情况是,只要有一个对象有一个不为 0 的 call 属性 / 方法,或者是 js_FunctionClass 类型,也就是这个对象里面有 function 标记的话,就会回传 function,其他情况则回传 object

这边引用开发者的解释,稍微说明一下 call 方法是什麽:

执行与此对象关联的代码。通过函数调用表达式调用。内部方法的参数是一个 this 值和一个包含调用表达式传递给函数的参数的列表。实现此内部方法的对象是可调用的。

简单说,一个对象如果支持了内部的 [[Call]] 方法,那麽他就可以被调用,就变成了函数,所以叫做函数对象。

另外,如果一个函数支持了内部的 [[Construct]] 方法,那麽就可以使用 new 或是 super 来调用,这时我们可以把这个函数称为「构造函数」。


写完这篇以後,感觉自己脑内的知识量暴增需要消化消化,但很开心能够完整的整理出一篇这样的文章,希望看过的人可以跟我一起知识量暴增^o^/

参考资料:
JS 原力觉醒 Day9 - 原始型别与物件型别
MDN Array.isArray()
进阶 Javasctipt 概念 (3)
JavaScript的typeof原理小记


<<:  [Day19] swift & kotlin 游戏篇!(1) 小鸡BB-游戏制作-按钮排版

>>:  Day27,Kubesphere 体验

Day 23 : Tkinter-利用Python建立GUI(基本操作及布局篇)

在进入Tkinter之前,先来讲讲GUI到底是甚麽。 GUI GUI其实就是图形使用者介面(Grap...

作业系统L5-行程排班

作业系统L5-行程排班 CPU-I/O分割 简介:CPU分割後接着IO分割 CPU排班程序 短程排班...

Day 15:如何解决 PowerShell 无法使用 Angular 指令的问题?

学习 Angular 的过程中,遇到了一些教学资源不见得会遇到的问题,还真是家常便饭,而且你个人电脑...

Day03 - 复习 canvas translate 与 rotate

今天简单复习一下 translate 与 rotate 用法,试着画圆饼 不免俗的设置 canvas...

[Day 22] 验证资料 — 不可以色色! 加装资料界的色情守门员

I used to be an adventurer like you, then I took ...