ECMAScript中有5种简单数据类型(也称为基本数据类型):Undefined、Null、Boolean、Number和String。还有一种复杂数据类型——Object,Object本质上是由一组无序的名值对组成的。
Undefined类型
Undefined类型只有一个值——undefined,它表示未定义,在使用var声明变量但未对其加以初始化时,这个变量的值就是undefined,例如:
var message;
alert(message == undefined);//true
Null类型
Null类型是第二个只有一个值的数据类型,这个值是null,从逻辑角度来看,null值表示一个空对象指针,所以使用typeof操作符检测null值时会返回“object”,比如:
var message = null;
alert(typeof message); //"object"
null表示一个“空”的值,它和 0 以及空字符串 ” 不同,0是一个数值,”表示长度为0的字符串,而null表示“空”。
实际上,undefined值是派生自null值的,因此ECMA-262规定对它们的相等性测试要返回true:
alert(null == undefined); //true
Boolean类型
Boolean类型只有两个字面值:true和false。可以直接使用true、false表示布尔值,也可以通过布尔运算计算出来:
true; //这是一个true值
false; //这是一个false值
2 > 1; //这是一个true值
2 >= 3; //这是一个false值
- &&运算是与运算,只有所有都为true,&&运算结果才是true;
- ||运算是或运算,只要其中一个为true,||运算结果就是true;
- ! 运算是非运算,它是一个单目运算符,把true变成false,false变成true;
布尔值经常用在条件判断中。
当我们对Number作比较时,可以通过比较运算符得到一个布尔值,要特别注意相等运算符 == 。Javascript在设计时,有两种比较运算符:第一种是 == 比较,它会自动转换数据类型再比较;第二种 === 比较,它不会自动转换数据类型,如果数据类型不一致,返回false,如果一致,再比较。比如下面的例子:
false == 0; //true
false === 0; //false
Number类型
JavaScript不区分整数和浮点数,统一用Number表示,一下都是合法的Number类型:
123; //整数123
0.123; //浮点数0.123
1.234e5; //科学计数法表示1.234X100000,等同于123400
-1; //负数
NaN; //NaN表示Not a Number,当无法计算结果时用NaN表示
Infinity; //表示无限大,当数值超过了JavaScript的Number所能表示的最大值时,就表示为infinity。
除了以十进制表示外,整数还可以通过八进制或十六进制的字面值来表示。其中,八进制字面值的第一位必须是0,然后是八进制数字序列(0~7),如果字面值中的数值超出了范围,那么前导零将被忽略,后面的数值将被当作十进制数值解析。比如:
var octalNum1 = 070; // 八进制的 56
var octalNum2 = 079; // 无效的八进制数值——解析为 79
var octalNum3 = 08; // 无效的八进制数值——解析为 8
十六进制字面值的前两位必须是 0X ,后跟任何十六进制数字(0~9及A~F)。字母可以大写也可以小写。
NaN这个特殊的Number**与所有其他值都不相等,包括它自己**:
NaN === NaN; /false
唯一能判断NaN的方法是通过isNaN()函数;
isNaN(NaN); // true
但是isNaN()有一个严重的缺陷,就是它的检查方式过于死板,如下面的例子:
var a = 2 / "foo";
var b = "foo";
window.isNaN(a);// true
window.isNaN(b);// true => 很明显"foo"不是一个数字,它也不是NaN
但是ES6有个工具函数是Number.isNaN()可以解决这个问题:
var a = 2 / "foo";
var b = "foo";
Number.isNaN(a);// true
Number.isNaN(b);// false
String类型
String 类型用于表示由零或多个 16 位 Unicode 字符组的字符序列,即字符串。字符串可以由双引号(”)或单引号(’)表示。
在加法运算中,如果只有一个操作符是字符串,则将另一个操作数转换为字符串,然后再将两个字符串拼接起来,比如:
var num1 = 5;
var num2 = 10;
var message = "The sum of 5 and 10 is " + num1 + num2;
alert(message); // "The sum of 5 and 10 is 510"
要把多个字符串连接起来,可以用+号连接:
var name = '小明';
var age = 20;
var message = '你好,'+name+',你今年'+age+'岁了!';
如果有很多变量需要连接,使用+号就比较麻烦了,ES6新增了一种模板字符串,表示方法和上面的多行字符串一样,但是它会自动替换字符串中的变量:
var name = '小明';
var age = 20;
var message = `你好, ${name}, 你今年${age}岁了!`;//注意是反引号`
alert(message);
- 字符串的一些常用方法:
toUpperCase()把一个字符串全部变为大写:
var s = 'Hello';
s.toUpperCase(); // 返回'HELLO'
toLowerCase()把一个字符串全部变为小写:
var s = 'Hello';
var lower = s.toLowerCase(); // 返回'hello'并赋值给变量lower
indexOf()会搜索指定字符串出现的位置:
var s = 'hello, world';
s.indexOf('world'); // 返回7
s.indexOf('World'); // 没有找到指定的子串,返回-1
substring()返回指定索引区间的子串:
var s = 'hello, world'
s.substring(0, 5); // 从索引0开始到5(不包括5),返回'hello'
s.substring(7); // 从索引7开始到结束,返回'world'
Object类型
ECMAScript中的对象其实就是一组数据和功能的集合。对象可以通过执行new操作符号后跟要创建的对象类型的名称来创建。而创建Object类型的实例并为其添加属性和方法,就可以创建自定义对象,如下所示:
var o = new Object();
JavaScript对象是一组由键-值组成的无序集合,例如:
var person = {
name: 'Bob',
age: 20,
tags: ['js', 'web', 'mobile'],
city: 'Beijing',
hasCar: true,
zipcode: null
};
JavaScript对象的键都是字符串类型,值可以是任意数据类型。上述person对象一共定义了6个键值对,其中每个键又称为对象的属性,例如,person的name属性为’Bob’,zipcode属性为null。
要获取一个对象的属性,我们用对象变量.属性名的方式:
person.name; // 'Bob'
person.zipcode; // null
数组
数组是一组按顺序排序的集合,集合的每个值称为元素。JavaScript的数组可以包括任何数据类型。例如:
[1, 2, 3.14, 'Hello', null, true];
创建数组可以通过Array()函数实现:
new Array(1, 2, 3); // 创建了数组[1, 2, 3]
也可以直接使用[]:
var arr = [1, 2, 3.14, 'Hello', null, true];
arr[0]; // 返回索引为0的元素,即1
arr[5]; // 返回索引为5的元素,即true
arr[6]; // 索引超出了范围,返回undefined
下面讨论如何判断一个变量是否是数组。
- 一般会想使用typeof,但是其实typeof并不起作用:
var ary = [1,23,4];
console.log(typeof ary); //输出结果是Object
由上面的例子可以看出,typeof并不能实时检测出是否是数组,只能判断其类型,所以说typeof判断基本类型数据还是挺好的,但是不能准确测试出是否是数组。
- instanceof判断
var ary = [1,23,4];
console.log(ary instanceof Array); //true;
从输出的结果上看,instanceof能准确检测出数据类型是否是数组,但是它也是有缺点的,就是它 判断的变量,必须在当前页面声明的。
- 原型链方法
var ary = [1,23,4];
console.log(ary.__proto__.constructor==Array);//true
console.log(ary.constructor==Array)//true 这两段代码是一样的
它的局限性也是跟第二个方法一样。比如,一个页面(父页面)有一个框架,框架中引用了一个页面(子页面),在子页面中声明了一个array,并将其赋值给父页面的一个变量,这时判断该变量,Array == object.constructor;会返回false;
原因:
(1) array属于引用型数据,在传递过程中,仅仅是引用地址的传递。
(2)每个页面的Array原生对象所引用的地址是不一样的,在子页面声明的array,所对应的构造函数,是子页面的Array对象,父页面来进行判断,使用的Array并不等于子页面的Array。
- 通用的方法
var ary = [1,23,4];
function isArray(o){
return Object.prototype.toString.call(o)=='[object Array]';
}
console.log(isArray(ary));