本文并不是对javascript的各个基本数据类型做详细的介绍,而是对javascript基本数据类型的疑难问题(特别是与其他语言不太一样的地方)做详细说明。
javascript包含六个基本的数据类型:String, Number, Boolean, Undefined, Null, Object。对于Null,Function是不是基本的数据类型,一直有争议,存在不同的说法。有些人认为Null不是一个数据类型,因为typeof null === 'object'
。有些人认为Function应该是一个基本的数据类型,因为 typeof function(){} === "function"
. 按照ecmascript规范的定义,Null是一个数据类型,而function是属于Object类型。 typeof的结果和javascript的基本数据类型不是一一对应的,这是浏览器实现的历史遗留问题(为了向后兼容)。
String, Number, Boolean, Undefined, Null是原始(primitive)类型(最近的es6中新增加了Symbol原始类型)。原始类型是值类型,而Object类型是引用类型。
下面将对基本数据类型中的一些疑难问题做详细说明。
javascript的字符串既可以用单引号来标识,也可以用双引号。在字符串有引号的时候,我们可以使用不同的引号来标识字符串,或将字符串中的引号转义。本节示例如下:
// 使用与字符串中不同的引号来标识字符串
'This is "Africa".'
"This is 'Africa'."
// 将字符串中的引号转义
"This is \"Africa\"."
'This is \'Africa\'.'
在javascript中没有char类型,我们可以用包含单个字符的字符串来替代char类型。我们可以使用String.prototype.charCodeAt方法将char转换成ASCII码,可以使用String.fromCharCode方法将ASCII码转换成char。本节示例如下:
"e".charCodeAt(0); // 101
String.fromCharCode(101); // "e"
javascript的字符串中可以使用Unicode字符(\u加4位16进制数字)。本节示例如下:
"兰芳\u5171\u548c\u56fd" // "兰芳共和国"
javascript中的数字可以用科学计数法表示,一般在数字太大或太小时使用。本节示例如下:
1.2e5; // 120000
1.2e-5; // 0.000012
javascript数字除了能用十进制表示外,还可以用8进制和16进制表示。数字的16进制表示,以"0x"起始,加上16进制数字(0-9A-F)。数字的8进制表示以"0"起始,加上8进制数字(0-8)。16进制数字和8进制数字都不能有小数,也不能用科学计数法表示。本节示例如下:
var a = 0xa3b; // 2619
var b = 072; // 58
b/2; // 29
0xa.3b; // SyntaxError: Unexpected token ILLEGAL
01e3; // SyntaxError: Unexpected token ILLEGAL
javascript数字类型有一个特殊的值NaN。NaN字面的意思就是"不是一个数字"(Not a Number)。在javascript中对非法的数据进行数字操作的时候就会返回NaN,当然对NaN进行数学运算也返回NaN。NaN的特殊之处还在与NaN不等于NaN,判断NaN可以使用全局函数isNaN.本节示例如下:
// 非法的数据进行数字操作
parseInt("a01"); // NaN
Math.sqrt(-1); // NaN
"b" * 1; // NaN
// 对NaN进行数学运算的结果为NaN
NaN + 1; // NaN
NaN * 12; // NaN
// NaN不等于NaN
NaN == NaN; // false
// 判断是否为 NaN
isNaN(NaN); // true
javascript数字类型还有一个特殊的值Infinity,用来表示无穷大(比任何其他的数字都要大)。javascript里的数字都在-infinity和infinity之间。本节示例如下:
1/0; // Infinity
9999/Infinity; // 0
Infinity/Infinity; // NaN
javascript布尔类型比较简单,只有两个取值(true/false)。 javascript中"&&","||"操作的运算结果并不一定是布尔型,也就是说运算结果并不会强制转换成布尔型。利用这个特性,我们常用"&&"来做条件赋值,用"||"来做默认值设置。本节示例如下:
// "&&", "||"计算结果不会转换成布尔型
1&&0; // 0
"tom" || "jerry"; // "tom"
// 使用"&&"条件赋值
var tom = {name: "tom", age: 10};
var age = tom && tom.age;
// 使用"||"设置默认值
var option = option || {country: 'China'};
Undefined类型只有一个值undefined,表示没有值。除显式的赋值为undefined外,下面情况下会产生undefined:
void(expression)
本节示例如下:
// 变量声明但没有赋值
var a;
a; // undefined
// 获取对象不存在的属性
var tom = {name: "tom", age: 10};
tom.gender; // undefined
// 函数没有返回值
function fn(){}
fn(); // undefined
function foo(){
return;
}
foo(); //undefined
// 函数的参数没有传入
function sum(x, y){
return y;
}
sum(1); // undefined
// void(expression)
void(0); //undefined
Null类型也只有一个值null。变量或属性赋值为null来表示空值。上文也已经提过,typeof null等于"object",而不等于"null",这个让人困惑的行为主要是为了向后兼容。本节示例如下:
var a = null;
typeof a; // "object"
对象是一组属性的集合。Javascript可以通过对象字面量创建对象,也可以使用构造函数创建对象。本节示例如下:
// 对象字面量创建对象
var obj = {name: 'jerry', age: 0};
// 通过构造函数创建对象
var obj = new Object({name: 'jerry', age: 0});
// 通过构造函数创建对象的另一种方式
var obj = Object({name: 'jerry', age: 0});
String/Number/Boolean/Array/Date继承自Object, 也就是说String/Number/Boolean/Array/Date对象都是一种Object对象, 它们可以使用Object中的属性和方法。这里可能有些让人迷惑,我们前面说了String类型/Number类型/Boolean类型,这里为什么又说String对象/Number对象/Boolean对象其实是一种Object对象。让我们先来看一个示例:
// 用字面量创建的,是原始类型
typeof "jerry"; // "string"
typeof 1; // "number"
typeof false; // "boolean"
// 用构造函数创建的,是Object类型
typeof new String("jerry"); // "object"
typeof Number(1); // "object"
typeof new Boolean(false); // "object"
// String/Number/Boolean等对象,可以使用Object中的属性和方法(hasOwnProperty/valueOf/toString都是Object的方法)
var a = new String("jerry");
a.hasOwnProperty("length"); // true
Number(1).valueOf(); // 1
new Boolean(false).toString(); // "false"
我们再来看个例子:
// 原始类型调用Obejct的方法
"jerry".hasOwnProperty("length"); // true
1.valueOf(); // SyntaxError: Unexpected token ILLEGAL
(1).valueOf(); // 1
false.toString(); // "false"
我们发现字面量创建的原始类型也能调用Object中的方法,这又是为什么呢?因为javascript引擎发现用原始类型调用Object的方法时,会把原始类型包装成Object类型, "jerry".hasOwnProperty("length")
等同于new String("jerry").hasOwnProperty("length")
。那为什么1.valueOf()
会语法错误呢?因为浏览器读到1.
时会认为要创建个小数,但是1.valueOf()
不是一个合法的小数。我们可以通过加括号的方式解决这个问题。
因为ecmascript里面并没有"基本类型"这个说法,对于javascript的基本类型的说法有争议,本文并不是想参与这些争论,而是介绍javascript类型中的疑难问题(特别是与其他语言不太一样的地方)。
进一步了解Javascript类型系统:
本文来自网易实践者社区,经作者魏文庆授权发布。