JavaScript 的七种内置类型:
- 空值(null)
- 未定义(undefined)
- 布尔值(boolean)
- 数字(number)
- 字符串(string)
- 对象(object)
- 符号(symbol,ES6 新增)
除对象之外,其他均为基本类型,对象可称为引用类型
1. 类型的判断
以下六种类型均有同名的字符串值与之对应:
typeof undefined === "undefined"; // true
typeof true === "boolean"; // true
typeof 42 === "number"; // true
typeof "42" === "string"; // true
typeof { life: 42 } === "object"; // true
typeof Symbol() === "symbol"; // true,// ES6 新加入的类型
1.1 null
通过 typeof
关键字对 null
进行取值,发现结果是 object
,这是 JavaScript 一直以来的一个语言上的 BUG,也许
永远不会修复,因为修复会带来更多的问题。
这是因为不同的对象在底层都表示为二进制,在 JavaScript 中二进制前三位都为 0 的话会被判断为 object
类型, null 的
二进制表示全部都是 0,自然前三位也是 0,所以执行 typeof 时会返回“object”。
typeof null === "object"; // true
1.2 function
通过 typeof
关键字对 function
进行取值,结果是 function
,但是它并不是一个内置类型,实际上是 object 的一个
子类型。概括来说,函数是可调用的对象。具体原因是它有一个内部属性 [[Call]]
,该属性让其可执行。
另外函数还有属性,其属性 length 就是声明的参数的个数。
typeof function a() {
/* .. */
} === "function"; // true
1.3 array
通过 typeof
关键字对 function
进行取值,结果是 object
,因为数组也是对象。准确的说是 object 的一个子类型,数组的元素是按照下表来索引,length 是元素的的个数。
所以通过 typeof
关键字无法区分出是否是数组。
typeof [1, 2, 3] === "object"; // true
1.4 通过 toString
判断类型
在任何值上调用 Object 原生的 toString()
方法,都会返回一个 [object NativeConstructorName]
格式的字符串。每个类在内部都有一个 [[Class]]
属性,这个属性中就指定了上述字符串中的构造函数名。
对于 Object 对象,直接调用 toString()
就能返回 [object Object]
。而对于其他对象,会直接返回内容的字符串,所以需要通过 call
or apply
来改变 toString()
的上下文来返回正确的类型信息。
不过此方法仅支持对内置对象的判断,不能检测非原生构造函数的构造函数名。
Object.prototype.toString.call(""); // [object String]
Object.prototype.toString.call(1); // [object Number]
Object.prototype.toString.call(true); // [object Boolean]
Object.prototype.toString.call(Symbol()); //[object Symbol]
Object.prototype.toString.call(undefined); // [object Undefined]
Object.prototype.toString.call(null); // [object Null]
Object.prototype.toString.call(newFunction()); // [object Function]
Object.prototype.toString.call(newDate()); // [object Date]
Object.prototype.toString.call([]); // [object Array]
Object.prototype.toString.call(newRegExp()); // [object RegExp]
Object.prototype.toString.call(newError()); // [object Error]
Object.prototype.toString.call(document); // [object HTMLDocument]
Object.prototype.toString.call(window); //[object global] window 是全局对象 global 的引用
再通过简单的处理,就可以获得需要的类型:
const type = Object.prototype.toString.call("").slice(8, -1).toLowerCase();
2. 值和类型
JavaScript 中的变量是没有类型的,只有值才有。变量可以随时持有任何类型的值。
2.1 undefined 和 undeclared
undefined(未定义)不同于 undeclared(未声明)。
已在作用域中声明但还没有赋值的变量,是 undefined 的。相反,还没有在作用域中声明 过的变量,是 undeclared 的。
var a;
a; // undefined
b; // ReferenceError: b is not defined
对于 undeclared(或者 not defined)变量,typeof 照样返回 "undefined"。这是因为 typeof
有一个特殊的安全防范机制。
var a;
typeof a; // "undefined"
typeof b; // "undefined"
既然 typeof
有此类的安全防范机制,那么可以利用此机制来检查一些可能不存在的 undeclared 的变量,如下:
// 这样会抛出错误
if (DEBUG) {
console.log("Debugging is starting");
}
// 这样是安全的
if (typeof DEBUG !== "undefined") {
console.log("Debugging is starting");
}