内容大纲:
js 有七种内置类型:null、undefined、boolean、numebr、string、object 和 symbol,可以使用 typeof 运算符来查看。
变量没有类型,但他们持有的值有类型。类型定义了值的行为特征。
很多开发人员将 undefined 和 undeclared 混为一谈,但在 js 中它们是两码事。undefined 是值的一种。而 undeclared 则表示变量还没有被声明过。
遗憾的是 js 却将它们混为一谈,在我们试图访问“undeclared”变量时这样报错:Refference Error: a is not defined,并且 typeof 对 undefined 和 undeclared 变量都返回“undefined”。
然而,通过 typeof 的安全防范机制(阻止报错)来检查 undeclared 变量,又是是个不错的方法。
内置类型
- 空值(null)
- 未定义(undefined)
- 布尔值(boolean)
- 数字(number)
- 字符串(string)
- 对象(object)
- 符号(symbol,ES6中新增)
除对象之外, 其他统称为“基本类型”
typeof 能返回类型的字符串值,但是typeof对 null 的处理会有问题
typeof null === "object"; // true
这个bug由来已久,也许永远不能修复,因为这牵涉到太多的Web系统。“修复”它可能会产生更多的bug。
我们需要用复合条件来检测null值的类型:
var a = null;
(!a && typeof a === "object"); // true
还有一种情况:
typeof function a(){/* .. */} === "function" // true
这样看来,函数也是js的一个内置类型。然而查阅规范就会知道,它实际上是object的一个“子类型”。具体来说,函数是“可调用对象”,他有一个内部属性[[Call]],该属性使其可以被调用。
值和类型
js中变量是没有类型的,只有值才有。变量可以随时持有任何类型的值。
var a = 42;
typeof a; // "number"
a = true;
typeof a; // "boolean"
undefined 和 undeclared
已在作用域中声明但是还没有赋值的变量,是undefined的。相反,还没有在作用域中声明过的变量,是undeclared的。
例如:
var a;
a; // undefined
b; // ReferenceError: b is not defined
浏览器对这类情况的处理令人抓狂。上例中,“b is not defined” 容易让人误以为是 “b is undefined”。其实,“undefined” 和 “is not defined” 是两码事。此时如果浏览器报错成 “b is not found” 会更准确。
更让人抓狂的是typeof处理 undeclared 变量的方式。例如:
var a;
typeof a; // "undefined"
typeof b; // "undefined"
请注意,b是一个undeclared的变量,但 typeof b 并没有报错是因为它有一个特殊的安全防范机制。
基于 typeof Undeclared 的安全防范机制
举个例子:
在程序中使用全局变量 DEBUG 作为“调试模式”的开关。在输出调试信息到控制台之前,我们会检查 DEBUG 变量是否已经被声明。顶层的全局变量声明 var DEBUG = true 旨在 debug.js 文件中才有,而该文件只在开发和测试时才被加载到浏览器,在生产环境中不予加载。
问题是如何在程序中检查全局变量 DEBUG 才不会出现 ReferenceError 错误。这时 typeof 的安全防范机制就成了我们的好帮手。
// ReferenceError
if (DEBUG) {
console.log( "Debugging is starting" );
}
// safe
if (typeof DEBUG !== "undefined") {
console.log( "Debugging is starting" );
}
还有另一种方法,就是检查所有全局变量是否是全局对象的属性,浏览器中的全局对象是 window。
if (window.DEBUG){
// ..
}
if (! window.DEBUG){
// ..
}
一些开发人员不喜欢通过 window 来访问全局对象,尤其当代码需要运行在多种 js 环境中时(不仅仅是浏览器,还有服务端,如 node.js 等),因为此时全局对象并非总是 window。
网友评论