【You Don't Know JS: Types & Grammar】Chapter 1 笔记

型别(types)相当于特徵,它们代表值(value)的行为。

譬如,开发者可以使用不同的方式处理89这个值。如果希望做算术运算,89的型别为(number);若只单纯存显示于页面上,此时89的型别可以为(string),端看开发者需要对值做何种的处理,而有不同的型别表示。

撰写程式码的过程当中,时常会用到型别转换,尤其是JS会以自己的方式去处理值的强制转型(value coercion),为避免强制转型将值转换成非预期的结果,所以了解每个型别相当重要。

譬如,型别为(number)的值89,当我们希望以字串的行为来处理这个值的时候,该值就必须先转型为(string),此时就可以取出位置为1的"9"这个字串。

内建型别

JS内建7大型别(built-in types)

nullundefinedbooleannumberstringobjectsymbol (ES6新增)

除了object之外,其他型别均为基本型别值(primitives)。

typeof运算子,会以字串的形式回传值的型别。
http://img2.58codes.com/2024/20112573TbIdTgstWU.jpg

需要特别注意的是null

如果使用typeof,会产生出乎意料的结果:
http://img2.58codes.com/2024/20112573U2Eekcj4tx.jpg

若需要确认型别是否为null,需使用複合条件。
http://img2.58codes.com/2024/20112573lRJSWC43lO.jpg

null是唯一个「falsy」的基型值。

那如果检查function呢?
http://img2.58codes.com/2024/20112573ULMQwyXeb4.jpg

这时会有个疑问是,型别显示function,但刚刚所提及的型别并没有function。

实际上function在JS中是属于object。

进一步的说,function是一个拥有[ [ Call ] ]内部特性,可以被呼叫的物件(callable object)。

既然function是object,所以也会拥有属性(properties)。
http://img2.58codes.com/2024/201125733Ysveu2v3Y.jpg

function a有一个length属性,代表宣告参数的数目。

那阵列(array)呢?
阵列也是object,具有2大特点:
1.
以数值化的方式索引,普通物件只能以字串为键值。
例如我们要取a阵列的第1个元素,可以使用a[0]的方式。
如若要取a物件的p属性,要使用a.p或是a['p']。
2.
会自动更新维护length属性。随着阵列元素的增加或减少,我们无须重新指定length属性的值,JS会自动计算当下阵列所有的元素数量。

在JS中,变数(variables)没有型别,值(value)才有型别。

变数可以随时拥有任的的值。

JS并非强型别的程式语言,当我们宣告一个变数持有string型别的值,下一个叙述句,此变数可以持有number,这在JS中是合法的。

89这个值的型别是number,其型别无法改变,我们可以透过强制转型(coercion)的方式,再另外建立一个型别为string的值"89"。

使用typeof的时候,表面上看似确认该变数的型别为何。
更为洽当的说法是,该变数所持有的那个值的型别为何。
http://img2.58codes.com/2024/20112573HjaxOeK369.jpg

未定义(undefined) & 未宣告(undeclared)

已宣告(declared),但未设定初始值的变数,预设值为undefined。
http://img2.58codes.com/2024/20112573U3OTreY0rz.jpg

使用typeof会回传"undefined"。

http://img2.58codes.com/2024/201125735D0dZKDEWO.jpg

未定义(undefined) & 未宣告(undeclared)实质上的差异

「undefined」表示在範畴中已经被宣告的变数,当下并没有其他的值,预设就是会给undefined。
注意,undefined也是一个值。

「undeclared」表示在範畴中并未宣告变数。

http://img2.58codes.com/2024/20112573rKjjSxs46x.jpg

浏览器的错误讯息是「b is not defined」,乍看之下似乎跟「undefined」一样,但实际上这是两种不同的情况,「b is not defined」错误讯息所代表的意思,等同于「undeclared」,并非「undefined」。

typeof使用于未宣告的变数会产生特别的行为:
http://img2.58codes.com/2024/20112573dRYkIOPnYG.jpg

请注意,b并未被宣告,执行typeof b的时候,没有错误被掷出,这是typeof的特殊防护机制。

type Undefined的安全机制

假设我们有一支debug.js程式,在其顶层宣告var DEBUG= true,藉此控制是否进入debug模式。

这支程式只会在开发过程载入,实际上线不会载入。

使用以下方式会掷出ReferenceError。

if (DEBUG) {    console.log('Debugging is starting');}

http://img2.58codes.com/2024/20112573FIPI0UpMiK.jpg

如果透过typeof的特性可以安全地检查

if (typeof DEBUG !== "undefined") {    console.log('Debugging is starting');}

另一种不使用typeof的特性,对于全域变数做检查,改从「所有的全域变数都是全域物件的属性」这个观点着手。

所以可以改成:

if (window.DEBUS) {    //...}

尝试存取一个不存在的物件属性不会掷出ReferenceError。

另一种情境是,当需要在别人的程式码中套入我们撰写的程式码,想要先检查他人的程式码是否有包含我们要使用的特定变数时,可以使用下列方式处理:

function doSomethingCool() {    var helper = (typeof FeatureXYZ !== "undefined") ? FeatureXYZ : function () {};    var val = helper();}

doSomethingCool()会先检查是否有FeatureXYZ这个变数,如果有,就使用;如果没有,就用我们自己的版本。

跟刚刚範例不同的是,FeatureXYZ是区域变数,不是全域变数,但我们依然可以使用typeof来做安全检查。

相同的情境,也可以使用「相依注入(dependency injection)」的方式。

function doSomethingCool(FeatureXYZ) {    var helper = FeatureXYZ || function () {}    var val = helper();}

以FeatureXYZ变数作为引数,再利用OR( || )的特性,检查FeatureXYZ是否存在。

关于OR( || )特性的说明

参考来源:
http://img2.58codes.com/2024/201125739FY75WdXxA.jpg

此为You Don't Know JS系列的笔记。


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章