ES5只有五种基本数据类型和一种复杂数据类型。
五种基本数据类型是:
- Undefined
- Null
- Boolean
- Number
- String
一种复杂类型是:
- Object Object本质上就是一个哈希表,有键值对构成
所有的值最终都是上述六种类型。使用typeof就可以获取值的数据类型,获取的类型和基本类型稍微有点不同
- Undefined 值未定义
- Boolean 布尔值
- Number 数值
- String 字符串
- Object 对象或者null
- function 函数
需要注意的是typeof是一种运算符而不是函数,所以 typeof 1 也可以获得number的返回值,不一定必须使用括号。
为什么基本类型里没有function,typeof的返回有呢,这是因为虽然从技术的角度将,function也是Object,但是它确实有一些特殊的属性,所以返回function是有意义的。
注意null也是Object
基本数据类型的使用
undefined
一个变量还未被初始化,就会是undefined类型,这里我们需要注意这样一种场景
var message;
alert(message); // undefined
alert(age); // 直接报错
alert(typeof message); // undefined
alert(typeof age); // undefined
由上面的例子我们可以看到,使用typeof判断undeifned并不能完全确定这个值是定义了没有初始化还是根本就没有定义。所以我们推荐在定义变量的时候,尽量要显示的初始化它以避免由此带来的undefined问题。
null
从逻辑的角度说,undefined指的是未定义,而null指的是空对象。我们在使用的时候,不应该将变量显示的初始化为undefined,但是应该将对象显示的初始化为null,这样我们在使用的时候就可以
if(a != null)
而在语言的角度将,undefined事实上是派生自null的,所以当我们判断他们俩相等的时候返回true
if(undefined == null) // true
这就告诉我们,在区分这两者的时候一定要从语义上也就是我们的使用上进行区分,定义的变量一定要初始化,定义的对象无法初始化的时候先初始化为null
Boolean
尝试将其他基本类型转为Boolean值
注意:
- 负值也是true
- undefined永远是false
Number
- 八进制,严格模式无效 再使用的时候前面加0 017 如果0后面加了非0-7的数字,则解析为十进制数字
- 10.0 在解析的时候解析为 10 因为存储浮点数需要更多的空间
- 3.15e7用来表示乘以十的七次方
- 不要测试浮点数运算结果 0.1+0.2 != 0.3
var a = 0.1; var b = 0.2; alert(a + b == 0.3); // false
- Infinity -Infinity用于数值超出最大范围的情况,判断它用IsFinite方法
- NaN用于表示本应该返回数字却没有返回数字的情况,在其他语言中这种情况就报错了,有了NaN就不会报错了。NaN由下面的特点
NaN/10 // 得到NaN,它参与任何运算都得到NaN NaN == NaN // false NaN不等于任意数字,甚至与自己也不相等 isNaN() // 判断是不是NaN,只要给的值能转换成数字,则不是NaN
当isNaN()用于对象的时候,更加神奇,它先调用对象的ValueOf看看能不能转换为数字,再调用ToString看看能不能转为数字。我们之后会发现,对象加上运算符,都是以这种方式进行运算的。
数值转换
数值转换比较复杂所以我们单独拿出来说,数值转换的方法有下面三种
Number();
ParseInt();
ParseFloat();
其中,Number方法的结果最为复杂,比如null转化为0,undefined转为NaN,这就给我们的使用带来了很大的不便。
所以我们要使用转为数字的时候尽量使用ParseInt,他的转换规则就很简单了,要么是数字,要么NaN
- String转换从前往后找,首位是数字,则一直往后找,直到数字结束,转化为数字,首位是字母则直接NaN
- 其他数据类型,不管是undefined还是null还是true false统统NaN
这就舒服多了。下面看一下转换不同进制数字的例子
ParseFloat的逻辑跟ParseInt一样,只注意下它能解析一个小数点,第二个小数点后面的数字也会被忽略,记住这个,剩下的两者都相同。
string
- 转义 \ 这个都在用,我们这里强调的是下面的用法,使用Unicode的十六进制来表示字符 \u
alert("\u03a3"); // Σ
- length属性返回字符串长度
- ToString方法可以指定数字转换的基数
- 对于null和undefined,调用toString会报错,如果不确定是不是null,可以用String()方法
var a = null; var b = undefined; a.toString(); // 报错 String(a); // null b.toString(); // 报错 String(b); // undefined
Object
在js中,Object是其他所有实例的基础,Object中的方法被全部实例共有,这里注意,DOM和BOM中的对象,可能不继承自Object,但是JS原生的对象一定继承Object,Object中定义的方法有:
- Constructor 构造函数
- hasOwnProperty(propertyName) 用于检查该实例中是否存在该属性(注意,是当前实例,并不检测原型链中有无该属性)
- isPrototypeOf(Object) 检查传入的对象是否是另一个对象的原型
- propertyIsEnumrable(propertyName) 检查给定的属性是否可以枚举
- isLocaleSrting() 返回对象的与地区对应的字符串表示
- toString() 返回字符串表示
- valueOf() 返回对象的字符串,数值或者布尔表示,通常和toString返回相同
ES6 - 字符串的解构赋值
- 由于字符串跟数组的渊源,字符串可以像数组一样进行解构赋值。
let [a, b, c] = 'hello'; alert(a); //h alert(b); //e alert(c); //l
- 由于字符串有length,所以其length可以进行对象的解构赋值
let {length: d} = 'hello'; alert(d); //5
ES6 - 字符串与Unicode
在以前,我们表示一个Unicode字符可以用下面的方式
'\u0061'
但是以前只支持四位,意思是只能处理 \u0000 到 \uFFFF,超过了这个大小,则无法正常解析,ES6改进了这个方法,使用大括号括起来,就可以解析任意大小的值
alert('\u{20BB7}'); //𠮷
至此,js要标识一个字符有下面六种方式
- ‘z’
- ‘\z’
- ‘\172’
- ‘\x7A’
- ‘\u007A’
- ‘\u{7A}’
在ES5,如果想把code转化为字符需要使用string.fromCharCode 但是这个方法无法处理大于四位的字符串,ES6提供了String.formCodePoint方法可以解决大于四位的问题
alert(String.fromCharCode(0x20BB7)); //ஷ
alert(String.fromCodePoint(0x20BB7)); //𠮷
alert(String.fromCodePoint(0x20BB7, 0x20BB7, 0x20BB7)); //𠮷𠮷𠮷 传多个参数就
反一下,如果我们想把字符转化为Unicode码,ES5中要用到CharAt或者CharCodeAt,这两者的区别是,如果值大于0xFFFF,CharAt会返回错误,CharCodeAt会返回两个值,即拆分成两个小于0xFFFF的值进行输出。在ES6中,提供了codePointAt,这个能够返回正确的码值。
let a = '𠮷a';
alert(a.codePointAt(0).toString(16)); //20bb7 返回正确
需要注意,在处理四字节字符和二字节字符混合的问题的时候,codePointAt传递的参数的索引值会有问题
ES6 -关于字符串的遍历
在之前,超过FFFF的字符码无法被遍历,ES6中字符串可以被使用for of遍历
let text = String.fromCodePoint(0x20bb7);
for (let i of text) {
alert(i);
}
ES6 - 模板字符串
使用`反引号,我们可以创建模板字符串,能实现下面的功能
- 保留换行和空格
alert(`12 abc `); // 换行和空格都会保留
- 内嵌变量 ${}
let a = 1; alert(`value is ${a}`); //value is 1
- 内嵌js语句
let a = 1; alert(`value is ${a + 1}`); //value is 2
- 内嵌函数调用
function func() { return '123'; } alert(`value is ${func()}`); //value is 123
- 作为函数体(lambda表达式我们之后还会讲到)
let func = name => `value is ${name}`; alert(func(1)); //value is 1
- 能够嵌套
let a = 1; alert(`this is ${`${a}`}`); //this is 1
ES6 字符串扩展方法
- String.raw 输出字符串的源字符串。如果字符串中含有\n这种换行符,raw返回的时候会返回\n以保证可以正常输出这个转义字符串(注意,这个函数不能使用括号调用,它是专门为模板字符串定义的方法,这个函数如果使用括号调用需要传入一个具有raw属性的对象,这里我们不做详细解释)
alert('1\n2'); //1 2(中间换行) alert(String.raw`1\n2`); //1\n2 实际上这个函数把\转化为\\了