一、内置类型
js共有7种内置类型:
- 空值(null)
- 未定义(undefined)
- 布尔值(boolean)
- 数字(number)
- 字符串(string)
- 对象(object)
- 符号(symbol, ES6新增)
除对象外,其他统称为“基本类型”
我们可用typeof来查看值的类型:
typeof undefined === "undefined"; // true
typeof true === "boolean"; // true
typeof 42 === "number"; // true
typeof "42" === "string"; // true
typeof { life: 42 } === "object"; // true
// ES6新增类型
typeof Symbol() === "symbol"; // true
null比较特殊,typeof对它处理有问题:
typeof null === "object"; // true
正确结果应该返回null,但这个bug由来已久,在js中已经存在了将近20年,由于牵涉到太多的Web系统,“修复”它会产生更多的bug,令许多系统无法修复。
我们需要使用符合条件来检测null的类型:
var a = null;
(!a && typeof a === "object"); // true
null是假值,也是唯一一个用typeof检测会返回“object”的基本类型
还有一种情况:
typeof function a() { /*...*/ } === "function"; // true
function也是js的一个内置函数。实际上是object的一个“子类型”。具体来说,函数是“可调用对象”,它有一个内部属性[[Call]],该属性使其可以被调用。
函数不仅是对象,还可以拥有属性。如:
function a(b, c) {
/*..*/
}
函数对象的length属性是其声明的参数的个数:
a.length; // 2
该函数声明了两个命名参数,b、c,所以其length值为2
typeof [1, 2, 3] === "object"; // true
数组也是对象,确切的说是object的一个“子类型”,数组的元素按数字顺序来进行索引,其length属性是元素的个数
三、值和类型
js中的变量是没有类型的,只有值才有。变量可以随时持有任何类型的值。js不做“类型强制”,语言引擎不要求变量总是持有与其初始值同类型的值。
在对变量执行操作时,得到的结果并不是该变量的类型,而是该变量持有的值的类型,因为js中的变量没有类型
var a = 42;
typeof a; // "number"
a = true;
typeof a; // "boolean"
typeof运算符总是会返回一个字符串:
typeof typeof 42; // "string"
typeof 42 = "number", typeof "number" = "string"
1、undefined和undeclared
变量在未持有值的时候为undefined,此时typeof返回“undefined”
var a;
typeof a;// "undefined"
var b = 42;
var c;
b = c;
typeof b; // "undefined"
typeof c; // "undefined"
大多数开发者倾向于undefined等同于undeclared(未声明),但在js中他们完全是两回事
- undefined:已在作用域中声明但还没有赋值的变量
- undeclared:还没有在作用域中声明过的变量
var a;
a; // undefined
b; // ReferenceError: b is not defined
undefined 和 is not defined是两码事。若此时浏览器报错成“b is not found” 或 “b is not declared”会更准确
var a;
typeof a; // "undefined"
typeof b; // "undefined"
对于undeclared变量,typeof照样返回"undefined"
虽然b是一个undeclared变量,但typeof b没报错,这是因为typeof有一个特殊的安全防范机制
2、typeof Undeclared
该安全防范机制对在浏览器中运行的js代码很有帮助,因为多个脚本文件会在共享的全局命名空间中加载变量。
如何在程序中检查全局变量DEBUG才不会出现RefrenceError错误,这是typeof的安全防范机制就能做到:
// 这样会报错
if (DEBUG) {
console.log("Debugging is staring");
}
// 这样是安全的
if (typeof DEBUG !== "undefined") {
console.log("Debugging is staring");
}
还有一种不通过typeof的安全防范机制的方法,就是检查所有全局变量是否是全局对象的属性,浏览器中的全局对象是window
if (window.DEBUG) {
// ..
}
if (!window.atob) {
// ..
}
与undeclared变量不同,访问不存在的对象属性(甚至是在全局对象window上)不会产生RefrenceError错误。