前言
在日常前端开发工作中,我们根据不同的场景需要后台返回不同的对象,有的返回一个字符串,有的需要返回 JSON
对象。
字符串:
var data = '{list: [{name: "小红", gender: "f"}, {name: "小明", gender: "m"}], success: true}'
JSON
对象:
我们怎么来判断这个对象是什么类型呢?这就要用到我们今天要讲的运算符:typeof
。
typeof
使用方法:
typeof operand
操作对象(operand)的类型将被返回。
请思考:工作中有什么情况需要用到 typeof
运算符?
原始类型
例如:
var num = 1;
typeof num; // 输出:'number'
下面有几个提供思考的问题,让我们一个一个来看。
问题1:
var s = 'jobs';
typeof 'jobs'; // 'string'
问题2:
var b = true;
typeof b; // 'boolean'
问题3:
var un;
typeof un; // 'undefined'
问题4:
var person = null;
typeof person; // 'object'
问题3输出 'undefined'
可以理解,问题4为什么输出的是 'object'
?
学过C语言的人知道有一个东西叫空指针,空指针的意思是不指向任何对象。 null
表示的是一个对象不指向任何对象的意思。在什么地方可以用到呢?
上图 null
的用法表示原型链的终点。
值得一提的是 javascript
的作者 Brendan Eich 自己说 null
的类型为 'object'
本身就是一个设计上的错误。只是后面为了兼容以前的版本,遗留了这个bug。
以上这些类型在 javascript
中叫做原始数据:
原始数据 (原始值、原始数据类型)不是一种 object 类型并且没有自己的方法的。在 JavaScript 中,有六种原始数据类型:string,number,boolean,null,undefined,symbol (new in ECMAScript 2015)。
函数
请再思考以下代码输出了什么:
typeof Number; // 'function'
typeof String; // 'function'
typeof Boolean; // 'function'
样子是不是似曾相识?看起来跟原始类型是一样的,以上类型为什么都为 'function'
?请看控制台的输出:
一目了然都是函数,所以类型都为 'function'
原始类型和其对应函数的关系
以下代码中的变量关系是什么呢?
var n1 = 1;
typeof n1; // 'number'
typeof Number; // 'function'
我们看下面的代码和图片:
var n1 = 1.2222;
var n2 = new Number(1.2222);
n1 == n2; // true
n1 === n2; // false
n1.toFixed(2); // 1.22
n2.toFixed(2); // 1.22
上面我们提到“不是一种 object 类型并且没有自己的方法”,所以这里我们需要关心的是 n1 为什么可以调用 toFixed 方法。解释如下:
虽然原始数据自己没有方法,但是在实际使用过程中会自动调用包装类型。包装类型是特殊的引用类型。每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而可能调用一些方法来操作这些数据。
思考一下它们之间的关系:
- 原始类型没有自己的方法;
- 原始类型在需要的时候会自动调用包装类型,在调用结束之后自动释放包装类型;
- 包装类型是
'function'
;
Function
以上顺利过关,再看下面代码:
请思考以下代码:
typeof Function
function foo() {};
typeof foo; // 'function'
typeof Array; // 'function'
typeof Date; // 'function'
为什么 Function 返回的是 'function'
,而 Array、Date等内建函数不是返回 'array'
和 'date'
呢?
一句话概括:因为 Array、Date 等内建对象是 Function 这个方法构建出来的。
对象
当我们知道了以上代码输出的原理,请再思考下面的代码:
typeof new Number(1.222); // 'object'
我们再来看上面那张图:
由此可知,所有由函数 new 出来的返回值都是对象。
请思考以下代码:
typeof {}; // 'object'
typeof []; // 'object'
typeof /pop/g; // 'object'
总结
typeof 可返回的值如下表所示:
类型 | 结果 |
---|---|
Boolean | “boolean” |
Number | “number” |
String | “string” |
Undefined | “undefined” |
Null | “object” |
Symbol (ECMAScript 6 新增) | “symbol” |
以上是ECMAScript 标准定义的 6 种数据类型 | |
任何其他对象 | “object” |
函数对象 | “function” |
注: typeof 只是一个运算符,其返回值并不能作为 javascript 类型系统的依据
题外话
有一个问题不知道大家有没有发现,为什么函数要返回 'function'
?
我为什么会有这个疑问,因为返回类型可以归纳为三大类
- 原始数据类型
'object'
'function'
有没有考虑过 Object 和 Function 这两个函数的关系。到底是 Object 创造了 Function, 还是 Function new 出了一个 Object?我发现这两个东西是鸡生蛋和蛋生鸡的关系。Object 方法是 Function 构造出来的,Function 里面的原型链又显示它的构造离不开 Object 的参与。由于这种说不清的关系,我们姑且就这么记住这三大类型吧。
它们之间的恩怨情仇,我下次有机会再跟大家分享。