简单来说,能够表示并操作的值的类型称做数据类型。在js中,有两种数据类型,一种是原始类型,另一种是对象类型(又称引用类型)。
原始类型包括有数字(Number)、字符串(String)、布尔值(Boolean)、Underfine和Null,在js中,除了上述的这几个外就是对象,对象是属性的集合,每个属性都由名值对构成。普通的js对象是“命名值”的无序集合,js中另一个特殊的对象——数组是带编号的有序集合。除此以外,还有一个特殊的对象就是函数,所以综上所述,对象类型有对象(Obejct)、数组(Array)和函数(Function)。对象、数组和函数会在以后讲到,现在主要讲的是类型。下面详细讲上面的细节。
一、数字(Number)
与其他编程语言不同,在JavaScript中是不区分整数值和浮点数值的。JavaScript中的所有数字均用浮点数值来表示。JavaScript采用的是IEEE754标准定义的64位浮点格式来表示数字,所以它能表示的最大值是正负1.7976931348623157e+308,最小值是正负5e-324。在JavaScript中,整数的范围是正负2的53次方,如果使用了超过这个数位的整数则无法保证低位数字的精度。在JavaScript中如数组索引和位操作符是基于32位整数的。
JavaScript的整数直接量有十进制的、十六进制的和八进制的。十六进制以0X为前缀,八进制以0为前缀,需要注意的是,在es6的严格模式中是不能用八进制的。JavaScript的浮点型除了可以采用传统写法(如1.2),也可以用科学计数法,也可以当数小于1的时候省略整数部分的0(如.3等于0.3)。
在Number中除了上述的这几种外,还有另外的特殊五种,一个是正极值(Number.MAX_VALUE)、负极值(Number.MIN_VALUE)、超过极值后的正无穷(Number.POSITIVE_INFINITY,值为Infinity)、负无穷(Number.NEGATIVE_INFINITY,值为-Infinity)以及不是数字的(NaN)。NAN是一个假值,是由于不是数字的String类型转换为Number类型后发生的错误而导致的。NaN他自身不相等,如果用alert(NaN==NaN)来输出的话,发现输出结果是false。判断一个值是否为NaN应该用isNaN()函数。
在数字类型中经常会遇见的一个问题是,假设变量x=0.3-0.2,变量y=0.2-0.1,那x和y是否会相等呢?答案是不会的。因为实数有无限个,但是JavaScript通过浮点数的形式只能表示其中有限的个数,也就是说,在JavaScript中,浮点数常常是真实值的一个近似表现。
在JavaScript中,支持复杂的算术运算,这些复杂的运算通过作为Math对象的属性定义的函数和常量来实现的。常用的几个如下所示:
Math.pow(2,3) //2的3次方 Math.round(0.6) //四舍五入 Math.ceil(0.6) //向上求整 Math.floor(0.6) //向下求整 Math.abs(0.6) //绝对值 Math.max(a,b,c) //最大值可填入多个参数 Math.min(a,b,c) //最小值,同上 Math.random() //生成一个0到1.0的随机数 Math.PI //圆周率
二、字符串(String)
在JavaScript中,字符串是一组由16位值组成的不可变的有序序列,每个字符通常来自于Unicode字符集。在这里解释一下16位值,因为JavaScript是采用UTF-16编码的Unicode字符集,字符串本身是一个字符数组,所以数组里每个元素都是占16bit的空间,也就是说是每个字符占用了两字节。在字符串中,可以用length方法来查看字符串的长度,字符串的索引是从0开始的。
在字符串的直接量中,可以用单引号和双引号,在js中,这两个是没什么区别的,但是在ECMAScript标准中,这就有区别了,在ECMAScript标准中,字符串的直接量只能用单引号或者反引号,像var a = "aaa"这样的声明在ECMAScript标准中是会报错的,应该是var a = 'aaa'或者var a = `aaa`,在ECMAScript标准中,单引号是用于静态的直接量而反引号是用于动态的直接量。常用的几个转义字符如下所示:
在JavaScript中,字符串的连接有两种方式,一种是用加号来连接,如:
var a = 'aa' + 'bb'
另一种是用join()方法。join()方法是把数组里所有元素输出成一个字符串,方法里面可以填入参数,该参数为分隔符。如:
如果不想输出有逗号则应该这样写:var a = ['a', 'b', 'c'] var b = a.join() //输出a,b,c var c = a.join('.') //输出a.b.c
var d = a.join('')下面列举字符串中常用的几个方法和属性:
var a = 'hello,world' console.log(a.charAt(0)) //获取第一个字符 console.log(a.substring(1,4)) //获取第二到第四个字符 console.log(a.slice(1,4)) //同上 console.log(a.indexOf('l')) //字符l首次出现的位置下标 console.log(a.lastIndexOf('l')) //字符l最后一次出现的位置下标 console.log(a.indexOf('l',3)) //字符l在下标3及之后出现的下标 console.log(a.split(',')) //以‘,’为分隔符,分割成两个子串 console.log(a.replace('h','H')) //将‘h’替换成‘H’ console.log(a.toUpperCase()) //所有字符大写 console.log(a.toLowerCase()) //所有字符小写 console.log(a.toLocaleLowerCase()) //同上 console.log(a.toLocaleUpperCase()) //所有字符大写 console.log(a.length) //获取字符串长度其中拿substring和slice、toUpperCase和toLocaleLowerCase以及toLowerCase和toLocaleLowerCase作详细的说明。
substring和slice的方法类似,但是在某些地方上只能用slice而不能用substring,如里面的参数是负数的时候,slice是查找倒数第几个,而substring则从0开始查找。
oUpperCase和toLocaleLowerCase以及toLowerCase和toLocaleLowerCase他们之间的用法没什么区别,但是在某些情况下只能用toLocaleLowerCase和
toLocaleLowerCase,比如(土耳其语)某些国家的文字则必须用这个方法才能转换大小写。
三、布尔值(Boolean)
这个类型只有两个值,就是true和false。常见的false值有:underfined、null、0、-0、NaN、“”(空字符串),所有的其他值,包括所有对象(数组)都会转换成true值。
四、null和underfined
尽管用alert(null == underfined)会输出一个true,但是实际上这两个是有很大的区别的,用alert(null === underfined)会输出false。首先先说一下这两个东西的共同点。他们如果是在布尔类型的地方都是假值,他们都不包含任何属性和方法,他们都表示空值。但是他们的不同是,首先null是一个对象,用typeof输出的是object,而underfined是全局对象里面的一个属性,一般认为underfined是由null里派生出来的。第二个不同是,null表示本来就没有的一个东西,而underfined只是表示一个变量没有赋值,变量没有赋值的原始值是underfined。还有就是当进行数字的类型转换,null会转换成0,而underfined则转换成NaN。
五、全局对象(global)
全局对象在JavaScript程序中可以直接使用,当JavaScript解释器启动时(或者任何Web浏览器加载新页面的时候),它将创建一个新的全局对象,并赋予一组定义的初始属性:
1.全局属性,如underfined、Infinity和NaN
2.全局函数,如isNaN()、parseInt()、eval()
3.构造函数,如Date()、RegExp()、String()、Object()、Array()
4.全局对象,如Math和JSON
在客户端的JavaScript中,Window对象定义了一些额外的全局属性。注意,在这里global对象与window对象还是有区别的,global对象是比window对象更上一级,也就是说,window对象其实是从global对象里派生出来的,global对象浏览器里不能直接输出来。global对象是最顶级的。一般的this引用的是global对象,但是在客户端中,也可以理解为this引用的是window对象。
在全局对象中有String()、Number()、Boolean()等构造函数,我们知道除了null和underfined没有属性和方法,其他的类型都有属性和方法,我们可以通过这些构造函数来将string、number和boolean这些不是对象的类型显式的转换成对象,通过他们对应的构造函数,如:
var a = new String('aaa') alert(typeof a) var b = 'aaa' alert(typeof b) alert(a == b)第一个输出的是对象第二个输出的是字符串,虽然两者之间比较是相等的,但是用三个等于号比较的时候返回的是false值。
六、原始类型和对象类型的区别
在JavaScript中,原始类型和对象类型的根本区别是原始类型是不可变的,而对象类型是可变的。也就是说,string、number、boolean、underfined和null的值是不可变的。比如:
var s = 'hello' s.toUpperCase()这个方法表面上看来是改变了s的值,但是实际上输出的是另一个字符串值,原来的s的值并没有发生改变。而在对象和数组里,则可以轻松的改变他的值,如:
var a = {x:1} a.x = 2a里面的x属性的值被改变了。值得一提的是,即使两个对象包含同样的属性及相同的值,他们也是不相等的。如:
var a = {x:1} var b = {x:1} alert(a === b)返回的是false值,若想要他们相等,则:
从上可以了解到,将对象赋值给一个变量,仅仅是赋值的引用值:对象本身并没有复制一次。如果想得到一个对象或数组的副本,则必须显示的复制对象的每个属性或者数组的每个元素,如:var a = {} var b = a b.x = 1 alert(a === b)
var deepCopy = function(source) { var result={}; for (var key in source) { result[key] = typeof source[key]==='object'? deepCoyp(source[key]): source[key]; } return result; } var a = {x:1, y:2, z:3}
七、类型转换
首先请看表:
在实际的开发中,数值型想要转换为字符串型的话可以通过如下方法:
var a = 1 + ''或者通过显式的方法,如:
var a = 1 a = String(a)或者用这种方法:
var a = 1 var b = a.toString() alert(typeof b)都可以将一个数值型转换成字符串型。在JavaScript中,可以通过Number()、String()、Boolean()和Object()来显式的转换类型。值得一提的是,null和underfined是没有toString()方法,因为这两个东西本身就没有方法,而且如果将这两个东西转换成对象的话会抛出异常,用object()方法的话则不会,只是返回一个空对象。
字符串型转换成数值型有两个方法,一个是parseInt()方法,返回的是整数,另一个是parseFloat()方法,返回的是浮点数,这两个方法都是全局函数,不属于任何类的方法。下面展示这两个方法的用法:
parseInt('3 abc') //返回3 parseInt('3.14') //返回3 parseInt('0xff') //返回255 parseInt('.1') //返回NaN,因为缺了个0 parseFloat('.1') //返回0.1,在浮点数里可以这样写 parseInt('11', 2) //返回3,后面的参数表示几进制