以下内容摘自阮一峰-JavaScript-标准参考教程
数据类型
JavaScript 语言的每一个值,都属于某一种数据类型。JavaScript 的数据类型,共有六种。(ES6 又新增了第七种 Symbol 类型的值)
数值(number):整数和小数(比如1和3.14)字符串(string):文本(比如Hello World)。布尔值(boolean):表示真伪的两个特殊值,即true(真)和false(假)undefined:表示“未定义”或不存在,即由于目前没有定义,所以此处暂时没有任何值null:表示空值,即此处的值为空。对象(object):各种值组成的集合。
通常,数值、字符串、布尔值这三种类型,合称为原始类型(primitive type)的值,即它们是最基本的数据类型,不能再细分了。对象则称为合成类型(complex type)的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。至于undefined和null,一般将它们看成两个特殊值。
对象是最复杂的数据类型,又可以分成三个子类型。
- 对象(object)
- 数组(array)
- 函数(function)
判断数据类型
JavaScript 有三种方法,可以确定一个值到底是什么类型。
- typeof运算符
- instanceof运算符
- Object.prototype.toString方法
typeof运算符
typeof运算符可以返回一个值的数据类型。
数值、字符串、布尔值分别返回number、string、boolean。
typeof 123 // "number"typeof '123' // "string"typeof false // "boolean"
函数返回function。
function f() {}typeof f// "function"
undefined返回undefined
typeof undefined// "undefined"
这个特点通常用在判断语句
if (typeof v === "undefined") { // ...}
对象返回object。
typeof window // "object"typeof {} // "object"typeof [] // "object"*
null返回object。
`typeof null // "object"
instanceof 运算符
instanceof运算符可以区分数组和对象。
instanceof运算符返回一个布尔值,表示某个对象是否为指定的构造函数的实例。var o = {};var a = [];o instanceof Array // falsea instanceof Array // truevar v = new Vehicle();v instanceof Vehicle // true
上面代码中,对象v是构造函数Vehicle的实例,所以返回true。
instanceof运算符的左边是实例对象,右边是构造函数。它会检查右边构建函数的原型对象(prototype),是否在左边对象的原型链上。因此,下面两种写法是等价的。
v instanceof Vehicle// 等同于Vehicle.prototype.isPrototypeOf(v)
由于instanceof对整个原型链上的对象都有效,因此同一个实例对象,可能会对多个构造函数都返回true。
var d = new Date();d instanceof Date // trued instanceof Object // true
上面代码中,d同时是Date和Object的实例,因此对这两个构造函数都返回true。
instanceof的原理是检查原型链,对于那些不存在原型链的对象,就无法判断。
Object.create(null) instanceof Object // false
上面代码中,Object.create(null)返回的新对象的原型是null,即不存在原型,因此instanceof就认为该对象不是Object的实例。
除了上面这种继承null的特殊情况,JavaScript 之中,只要是对象,就有对应的构造函数。因此,instanceof运算符的一个用处,是判断值的类型。
var x = [1, 2, 3];var y = {};x instanceof Array // truey instanceof Object // true
上面代码中,instanceof运算符判断,变量x是数组,变量y是对象。
注意,instanceof运算符只能用于对象,不适用原始类型的值。
var s = 'hello';s instanceof String // false
上面代码中,字符串不是String对象的实例(因为字符串不是对象),所以返回false。
此外,对于undefined和null,instanceOf运算符总是返回false。
undefined instanceof Object // falsenull instanceof Object // false
利用instanceof运算符,还可以巧妙地解决,调用构造函数时,忘了加new命令的问题。
function Fubar (foo, bar) { if (this instanceof Fubar) { this._foo = foo; this._bar = bar; } else { return new Fubar(foo, bar); }}
上面代码使用instanceof运算符,在函数体内部判断this关键字是否为构造函数Fubar的实例。如果不是,就表明忘了加new命令。
Object.prototype.toString()
toString方法的作用是返回一个对象的字符串形式,默认情况下返回类型字符串。
var o1 = new Object();o1.toString() // "[object Object]"var o2 = {a:1};o2.toString() // "[object Object]"
上面代码表示,对于一个对象调用toString方法,会返回字符串[object Object],该字符串说明对象的类型。
字符串[object Object]本身没有太大的用处,但是通过自定义toString方法,可以让对象在自动类型转换时,得到想要的字符串形式。var obj = new Object();obj.toString = function () { return 'hello';};obj + ' ' + 'world' // "hello world"
上面代码表示,当对象用于字符串加法时,会自动调用toString方法。由于自定义了toString方法,所以返回字符串hello world。
数组、字符串、函数、Date 对象都分别部署了自定义的toString方法,覆盖了Object.prototype.toString方法。
[1, 2, 3].toString() // "1,2,3"'123'.toString() // "123"(function () { return 123;}).toString()// "function () {// return 123;// }"(new Date()).toString()// "Tue May 10 2016 09:11:31 GMT+0800 (CST)"
上面代码中,数组、字符串、函数、Date 对象调用toString方法,并不会返回[object Object],因为它们都自定义了toString方法,覆盖原始方法。
**toString() 的应用:判断数据类型
Object.prototype.toString方法返回对象的类型字符串,因此可以用来判断一个值的类型。**var obj = {};obj.toString() // "[object Object]"
上面代码调用空对象的toString方法,结果返回一个字符串object Object,其中第二个Object表示该值的构造函数。这是一个十分有用的判断数据类型的方法。
由于实例对象可能会自定义toString方法,覆盖掉Object.prototype.toString方法,所以为了得到类型字符串,最好直接使用Object.prototype.toString方法。通过函数的call方法,可以在任意值上调用这个方法,帮助我们判断这个值的类型。
Object.prototype.toString.call(value)
上面代码表示对value这个值调用Object.prototype.toString方法。
不同数据类型的Object.prototype.toString方法返回值如下。
数值:返回[object Number]。字符串:返回[object String]。布尔值:返回[object Boolean]。undefined:返回[object Undefined]。null:返回[object Null]。数组:返回[object Array]。arguments 对象:返回[object Arguments]。函数:返回[object Function]。Error 对象:返回[object Error]。Date 对象:返回[object Date]。RegExp 对象:返回[object RegExp]。其他对象:返回[object Object]。
这就是说,Object.prototype.toString可以看出一个值到底是什么类型。
Object.prototype.toString.call(2) // "[object Number]"Object.prototype.toString.call('') // "[object String]"Object.prototype.toString.call(true) // "[object Boolean]"Object.prototype.toString.call(undefined) // "[object Undefined]"Object.prototype.toString.call(null) // "[object Null]"Object.prototype.toString.call(Math) // "[object Math]"Object.prototype.toString.call({}) // "[object Object]"Object.prototype.toString.call([]) // "[object Array]"
利用这个特性,可以写出一个比typeof运算符更准确的类型判断函数。
var type = function (o){ var s = Object.prototype.toString.call(o); return s.match(/\[object (.*?)\]/)[1].toLowerCase(); }; type({}); // "object" type([]); // "array" type(5); // "number" type(null); // "null" type(); // "undefined" type(/abcd/); // "regex" type(new Date()); // "date"在上面这个type函数的基础上,还可以加上专门判断某种类型数据的方法。var type = function (o){ var s = Object.prototype.toString.call(o); return s.match(/\[object (.*?)\]/)[1].toLowerCase();};['Null', 'Undefined', 'Object', 'Array', 'String', 'Number', 'Boolean', 'Function', 'RegExp'].forEach(function (t) { type['is' + t] = function (o) { return type(o) === t.toLowerCase(); };});type.isObject({}) // truetype.isNumber(NaN) // truetype.isRegExp(/abc/) // true
null 和 undefined
null与undefined都可以表示“没有”,含义非常相似。将一个变量赋值为undefined或null,老实说,语法效果几乎没区别。
在if语句中,它们都会被自动转为false,相等运算符(==)甚至直接报告两者相等。
if (!undefined) { console.log('undefined is false');}// undefined is falseif (!null) { console.log('null is false');}// null is falseundefined == null// true
null是一个表示“空”的对象,转为数值时为0;undefined是一个表示”此处无定义”的原始值,转为数值时为NaN
Number(null) // 05 + null // 5Number(undefined) // NaN5 + undefined // NaN
null,undefined 用法
对于null和undefined,大致可以像下面这样理解。null表示空值,即该处的值现在为空。调用函数时,某个参数未设置任何值,这时就可以传入null,表示该参数为空。比如,某个函数接受引擎抛出的错误作为参数,如果运行过程中未出错,那么这个参数就会传入null,表示未发生错误。
undefined表示“未定义”,下面是返回undefined的典型场景。
// 变量声明了,但没有赋值var i;i // undefined// 调用函数时,应该提供的参数没有提供,该参数等于 undefinedfunction f(x) { return x;}f() // undefined// 对象没有赋值的属性var o = new Object();o.p // undefined// 函数没有返回值时,默认返回 undefinedfunction f() {}f() // undefined
布尔值
布尔值代表“真”和“假”两个状态。“真”用关键字true表示,“假”用关键字false表示。布尔值只有这两个值。
下列运算符会返回布尔值:
两元逻辑运算符: && (And),|| (Or)前置逻辑运算符: ! (Not)相等运算符:===,!==,==,!=比较运算符:>,>=,<,<=
如果 JavaScript 预期某个位置应该是布尔值,会将该位置上现有的值自动转为布尔值。转换规则是除了下面六个值被转为false,其他值都视为true。
undefinednullfalse0NaN""或''(空字符串)
布尔值往往用于程序流程的控制,请看一个例子。
if ('') { console.log('true');}
// 没有任何输出
上面代码中,if命令后面的判断条件,预期应该是一个布尔值,所以 JavaScript 自动将空字符串,转为布尔值false,导致程序不会进入代码块,所以没有任何输出。注意,空数组([])和空对象({})对应的布尔值,都是true。
if ([]) { console.log('true');}// trueif ({}) { console.log('true');}// true