JavaScript中的变量是没有类型的,只有值才有。变量可以随时持有任何类型的值。
JavaScript不做“类型强制”;就是说,语言引擎不要求变量总是持有与其初始值同类型的值。一个变量可以现在被赋值为字符串类型值,随后又被赋值为数字类型值。
在对变量执行typeof操作时,得到的结果并不是该变量的类型,而是该变量持有的值得类型,因为JavaScript中的变量没有类型。

  1. var a = 42
  2. typeof a // "number"
  3. a = true
  4. typeof a // "boolean"

typeof操作符总会返回一个字符串

  1. typeof typeof 42 // "string"

typeof 42 首先返回一个字符串”number”,然后typeof “number”返回”string”

undefined和undeclared

变量在未持有值的时候是undefined。此时typeof 返回”undefined”

  1. var a
  2. typeof a //"undefined"
  3. var b = 42
  4. var c
  5. b = c
  6. typeof b // "undefined"
  7. typeof c // "undefined"

已在作用域中声明但还没有赋值的变量,是undefined。相反,还没有在作用域中声明过的变量,是undeclared

  1. var a
  2. a // undefined
  3. b // ReferenceError:b is not defined

注意:typeof处理undeclared变量的方式。

  1. var a
  2. typeof a // "undefined"
  3. typeof b // "undefined"

对于undeclared(或者not defined)变量,typeof照样返回”undefined”。虽然b是一个undeclared变量,但 typeof b 并没有报错。这是因为typeof有一个特殊的安全防范机制。
如果typeof如果能返回undeclared(而非undefined)的话,情况会好很多。

typeof Undeclared

该安全防范机制,对在浏览器中运行的JavaScript的代码来说,还是很有帮助的,因为多个脚本文件会在共享的全局命名空间中加载变量。
如果要为某个缺失的功能写polyfill(即衬垫代码或者补充代码,用来补充当前运行环境中缺失的功能),一般不会用 var atob 来声明变量 atob 。如果在if语句中使用 var atob ,声明会被提升(hoisted)到作用域(即当前脚本或函数的作用域)的最顶层,即使if条件不成立也是如此(因为atob全局变量已经存在)。在有些浏览器中对于一些特殊的内建全局变量(通常称为“宿主对象”,host object),这样的重复声明会报错。去掉var则可以防止声明被提升。
还有一种不用通过 typeof 的安全防范机制的方法,就是检查所有全局变量是否是全局对象的属性,浏览器中的全局对象是window。
与undeclared变量不同,访问不存在的对象属性(甚至是在全局对象window上)不会产生ReferenceError错误。
一些开发人员不喜欢通过window来访问全局对象,尤其当代码需要运行在多种JavaScript环境中(不仅仅是浏览器还有服务器端如nodejs等),因为此时全局对象并非总是window。
typeof的安全防范机制还可以用来检测非全局变量,比如:

  1. var helper = (typeof FeatureXYZ !== "undefined") ? FeatureXYZ : function(){}

这里FeatureXYZ并不是一个全局变量,但仍然可以使用typeof的安全防范机制来做检查。