定义

许多开发者认为动态语言没有类型。然并卵!本文对“类型”(Type)的定义为:

一种语言中具有固有特性的值,能从行为上区分与其他值是不同的,解释器与人都能理解这种区别。

类型为什么如此重要

只有了解类型的固有特性,才能知道如何恰当的对其强制转型(Coercion)(见 第四章 强制转型),而且JS ( JavaScript )的转型有时候非常诡异,许多开发者认为这是JS语言的糟粕因此敬而远之,只有深入了解了JS的类型(Types)与值(Values)之后,才能真正理解和发挥强制转型的威力。

内置类型(Build-in Types)

JS中有7(6+1)种内置类型

  1. string
  2. boolean
  3. number
  4. object (包括Function Array Date Error RegExp String Boolean Number )
  5. null
  6. undefined
  7. symbol (es6新加入,详见 第三章 )

而查看内置类型的方法就是 typeof ,返回一个字符串

typeof "string";  //=> "string"
typeof 1;  //=> "number"
typeof null; //=> "object"

关于null的bug,这个历史遗留问题,判断null的方法

!null && typeof null === "object"; // true

既然 typeof 不能显示 null,那是不是typeof 只能返回6种类型呢?答案当然是错啦,因为还有

typeof function(){};  //=> "function"
typeof Function;  //=> "function"
typeof [];  //=> "object"

简直哔了狗了,同样是对象,函数凭什么就比数组等另外6对象子类高级,还占了一个 typeof ! 道理我们都懂,就是因为函数作为对象的子类型,有个隐藏的 [[Call]] 属性,函数就是一个可以调用的对象,然而另外6对象子类并没有这种待遇。

跑题1 关于 function 与 另外6对象子类的区别

既然function 与 另外6对象子类 都是对象,那就可以看看对象都有哪些属性

var foo = function (a,b,c) {};
var arr = [1,2,3];
Object.keys(foo)  //=> []
Object.keys(arr)  //=> ["0", "1", "2"]

WTF!! 为什么没有属性?因为Object.keys()只能返回可枚举属性,而不可枚举属性需要用Object.getOwnPropertyNames()获取

Object.getOwnPropertyNames(foo)  //=> ["length", "name", "arguments", "caller", "prototype"]
Object.getOwnPropertyNames(arr)  //=> ["0", "1", "2", "length"]
Object.getOwnPropertyNames(/1/) //=> ["lastIndex"]
Object.getOwnPropertyNames(new Error())  //=> ["stack"]
...等

这次总算出来了,用chrome开发者工具 console.dir(foo) 看下是这样的:

enter image description here

可是这些属性有什么卵用呢?目前只知道函数的length属性是参数的数量,name属性是函数的名字,prototype不用说了(见 YDKJS第二本书),其他的到底是什么鬼?谁能告诉我。

值(Values)与类型(Types)

在JS中,变量(Variables)是没有类型,变量只是个盒子,里面放着值,值才有类型。也就是说JS不会认为一个变量只能保存同一种类型的值。而值的类型是不会改变的,通过某种方法把一种类型转换并返回另一种类型的值的过程叫 强制转型(Coercion)(见 第四章

undefined 与 未声明(undeclared)

undefined 的字面意思是“未声明”,然而 undefined 在 JS 中与 "string"、1、{a:1}、true 这些内置类型一样,也是一种值的类型,只不过它就是叫 undfined。

比如:

var a; 
a //=> undefined
b //=> Uncaught ReferenceError: b is not defined

我的理解是 a 作为一个变量,相当于告诉JS我有一个叫“a”的盒子,但是并没有赋值,而这个盒子里自带了一个叫 undefined 的值,而我并没有告诉JS我有一个叫 “b”的盒子,所以会报错,因为JS找不到这个叫“b”的盒子,所以a就是声明但未赋值,自带undefined值的盒子,而b就是未声明的盒子。

使用 typeof 检查未声明变量

之前 b 作为没有声明的变量,如果在编写代码时不小心用到了 b ,就会导致报错,程序中断,而使用typeof可以避免这个问题

typeof b; //=> "undefined"

WTFFFF! 这到底什么鬼,说好的未声明的变量 b,为什么用typeof检测它会出现 undefined !! 虽然不知道为什么,但是可以利用这个特性来检查是否有变量已经被声明过了,因为有时候你需要加载多个JS文件,万一别人声明过的变量你也想用怎么办呢,就可以用 typeof 检查一下。

虽然使用全局变量是非常不好的行为,但是...书上就是这么举例的,如果谁有更好的例子麻烦告诉我,谢谢。

本章小结

  1. JS 有 7 种内置类型
  2. typeof 可以显示JS中值的类型,function虽然不是内置类型,但 typeof 会显示它,null是一种内置类型,typeof却会显示它为“object”。也就是说 typeof 不是一个女子方法,怪不得JS被认为有很多糟粕。
  3. undefined 与 未声明 是不一样的,undefined 是一种内置类型,未声明是从来没出现过的变量
  4. 可以用 typeof 检查未声明变量,这样可以避免触发引用错误