了解了前面的入门内容,其实已经可以开始尝试上手写一些简单的JavaScript代码了,不过如果想要真正的不踩坑,所有开发语言都绕不过的几大专题都还是需要了解的,包括:
- 数据类型
- 运算符
- 开发语法
- 标准库
- 面向对象编程
还有些JavaScript比较擅长或者是独有的专题,包括:
- 异步操作
- DOM
- 事件
- 浏览器模型
这里先从最最基础的数据类型开始了解。
1. 概述
JavaScript的所有值,都分别属于某一种数据类型,到ES 6为止,共有7种类型,包括有:
- 数值(number):整数和小数(比如1和2.2)
- 字符串(string):文本(比如Everybody Loves Eileen)。
- 布尔值(boolean):表示真伪的两个特殊值,即true(真)和false(假)
- undefined:表示“未定义”或不存在,即由于目前没有定义,所以此处暂时没有任何值
- null:表示空值,即此处的值为空
- 对象(object):各种值组成的集合
- Symbol:独一无二的值,可以保证不会与其他属性名产生冲突
其中,数值、字符串、布尔值以及ES 6新增加的Symbol被称为原始类型(primitive type)值,因为它们是最基本的数据类型无法再被细分;undefined和null属于特殊值。
对象则称为合成类型(complex type)值,因为一个对象往往是多个原始类型值的合成,更像是存放各种值的容器;它比较复杂,又可细分为三个子类型:
- 狭义的对象(object):后文所有对象都特指该子类型;
- 数组(array):与对象有不同的数据组合方式;
- 函数(function):处理数据的方法,JavaScript把它也当作一种数据类型,可以赋值给变量,是函数式编程的基础。
2. 内置的类型识别方法
JavaScript有三种方法可以确定一个值究竟是什么类型:
- typeof 运算符
通过该运算符,可以返回一个值的数据类型。
如下图:
由于typeof是可以判断一个变量是否未定义的,所以经常可以在判断语句当中是用来确认一个变量是否有效,如下:
if (typeof x !== 'undefined') {
// ...代码
}
不过针对对象,它的用途就不明确了,如下图:
可以看出typeof是无法识别对象或者数组的,这种情况下,有必要使用其他的方式来区分对象和数组,可以考虑使用instanceof运算符。
同时也应该发现到null也被识别为了对象,这个是由于历史原因造成的,在最初版本设计之初,其实只设计了5中数据对象(对象、整数、浮点数、字符串和布尔值),并没有考虑过null,而是把它作为了对象的一种特殊值。尽管后来独立出来作为单独的数据类型,但是为了兼容以前的代码,typeof null的返回值object就无法更改了。
- instanceof 运算符
instanceof是从Java引入的运算符,本质上就是用来判断一个实例是不是属于某种类型的,所以并不局限于对象,它是可以用来判断绝大多数的数据类型,不过因为它的返回值只有真伪两种,也就是说,开发者在使用它的时候需要先自己明确需要判断的类型,比如:
如果自己无法确定,就会出现上图的情况,一个数组x,它可以判断为数组,但也可以判断为对象,因为数组本身是对象的子类型;所以必须要明确地知道自己需要进行什么判断。
注:在实际使用过程中,由于语言规范中对于instanceof运算符的定义是需要含有一个HasInstance方法的,如果没有该方法则结果直接返回false,故此请勿使用它来对Number、String、Boolean和undefined进行判断,因为它们都是不能够再进行细分的数据类型。
- Object.prototype.toString.call() 方法
如果真的要判断某个对象值究竟属于那种类型,上述两种方法都各有弊端,那么有没有更靠谱一点的方法呢?
在不自己构建函数,比引用外部组件的情况下,最佳选择莫过于Object.prototype.toString.call()这个方法了,如:
这个方法,基本上所有的数据类型都可以分辨出来,至于ES 6新加入的Symbol,我们也可以看看测试结果:
所以基本都是没什么问题的;同时它还可以帮你检查出对象的更细节的类型,比如:日期时间类型(Date)、数学类(Math)、正则表达式(RegExp)等等这些特殊的对象,都可以正确的识别出来,可谓很强大了。
3. 特殊类型:null和undefined
看完了上面的如何分辨数据类型,我们会发现两个非常特殊的类型:null和undefined
虽然我们大概说明过了它们,但还是需要详细的了解,才能更好的避免踩坑。
3.1 历史
事实上在各类开发语言当中,你都很难见到undefined这个类型的身影,在表现形式上甚至使用上,undefined和null都非常的相似:
如上图,在使用==(相等运算符)比较两者时,结果甚至是相等的!
当然由于它们分别属于不同的数据类型,使用全等运算符===(也就是严格相等运算符)的时候,它们不同。
既然含义和用法都差不多,为什么会出现一个undefined类型,徒然增加了复杂程度呢?
这与历史原因有关。
1995年 JavaScript 诞生时,最初像 Java 一样,只设置了null表示"无"。根据 C 语言的传统,null可以自动转为0。
但是,JavaScript 的设计者 Brendan Eich,觉得这样做还不够。首先,第一版的 JavaScript 里面,null就像在 Java 里一样,被当成一个对象,Brendan Eich 觉得表示“无”的值最好不是对象。其次,那时的 JavaScript 不包括错误处理机制,Brendan Eich 觉得,如果null自动转为0,很不容易发现错误。
因此,他又设计了一个undefined。区别是这样的:null是一个表示“空”的对象,转为数值时为0;undefined是一个表示"此处无定义"的原始值,转为数值时为NaN(Not a Number ,非数字),如下图:
3.2 用法和含义
对于容易混淆的初学者,我个人建议这样理解:
null表示空值,和其他语言一样,它的出现不会造成运行错误,是一个真实存在的值。
undefined则表示未定义,它会造成运行错误,主要会出现在下列场景中:
// 变量声明了,但没有赋值
var i;
i // undefined
// 调用函数时,应该提供的参数没有提供,该参数等于 undefined
function f(x) {
return x;
}
f() // undefined
// 对象没有赋值的属性
let o = new Object();
o.p // undefined
// 函数没有返回值时,默认返回 undefined
function f() {}
f() // undefined
评论
发表评论