1 数据类型
JavaScript里共有7中数据类型,分别为:
数值(number):整数和小数
字符串(string):字符串
布尔值(boolean):表示真假的两个值,true和false
undefined:表示暂未定义
null:表示空值
对象(object):复合类型,各种值的集合
symbol:ES6新增
一般将数值、字符串、布尔值、undefined、null称为基本类型,对象称为复杂类型,它是由各种值组合而成的。
对象(object)根据特征可分为三类:
狭义的对象(object)
数组(array)
函数(function)
2 数值(number)
2.1 数值的存储
在JavaScrpit中,所有的数值是以64位浮点数的形式存在的(所以JavaScript实际上没有整数,整数也是以64位浮点数的形式储存的)
在64位浮点数里
第1位:符号位
第2-12位:数值的指数部分
第13-64位:数值的小数部分
[图片上传失败...(image-ffb4a1-1526190778004)]
2.1.1 符号位
表示数值的正负,0为正,1为负
2.1.2 指数部分
指数部分共有11位,所以其最大值为(2047),但是指数要分正负,所以引入了一个偏差值(Bias),为-1023。指数部分储存的数全是正数,但加上偏差值,就有了负数部分。比如:指数部分是00000000000
的话,计算机加上偏差值之后最终结果就变成了-1023,就能表示负的指数了。
指数部分的最终能表示[-1023,1024],那么一个64位浮点数能表示的数值为,不包括和
如果一个数大于,那么就会发生“正向溢出”,即无法表示,返回Infinity
如果一个数小于(利用指数部分能表示的最小值是,加上64位浮点数小数部分的52位,共75位),那么就会发生“负向溢出”,无法表示,返回0
Math.pow(2,-1076) //0
Math.pow(2,-1075) //5e-324
Math.pow(2,1024) //Infinity
Math.pow(2,1023) //8.98846567431158e+307
2.1.3 小数部分
IEEE 754规定,如果指数部分的值在(0,2047)之间,那么有效数字的第一位总是1,这个1没有保存在64位浮点数之中,也就是说XXX……XXX
是64为浮点数的小数部分的话,那么实际的小数部分为1.XXX……XXX
,相当于自动给有效数字部分增加了一位,共53位
综上所述,一个数值在JavaScript当中的表现形式为:
(-1)^符号位*1.小数部分*2^指数部分
2.2 数值的表示
虽然数值在计算机的底层是以64位浮点数的形式储存的,但在JavaScript中是以方便人能理解的形式表示的,比如说科学计数法,进制法等
2.2.1 科学计数法
科学计数法以字母e或E后面跟整数表示数值的指数部分
123E2
123E-2
-1.23E2
.123E2
有两种情况,数值会自动转化为科学计数法
小数点前面的数字大于21位
1234567890123456789012 // 1.2345678901234568e+21
123456789012345678901 // 123456789012345680000
小数点后的0多余5个
0.0000003 // 3e-7
0.000003 // 0.000003
在数值转字符串的时候要特别注意,科学计数法转字符串会产生不一样的结果
2.2.2 进制
常用的进制有4种,分别为二进制、八进制、十进制、十六进制
二进制:前缀为
0b
或者0B
八进制:前缀为0o
或者0O
,或者前缀只有0
,但是后续数字只有0~7
十进制:无前缀
十六进制:前缀为0x
或者0X
八进制的前缀0
表示法很容易引起错误,ES5的严格模式和ES6已经废弃了,不过浏览器还兼容
在JavaScript中,会默认将数值转为十进制。如果数值出现了不属于该进制里的数字,会报错
2.3 一点特殊值
2.3.1 0的正负
在64位浮点数里面,由于存在一个表示正负的位,所以每个数字都有正负,0
也有+0
和-0
,它们几乎是等价的,除了它们当分母的时候
+0 //0
-0 //-0
(+0).toString() //"0"
(-0).toString() //"0"
(1/+0)===(1/-0) //false
(1/+0) //Infinity
(1/-0) //-Infinity
2.3.2 NaN
NaN
是一个特殊值,表示“非数字”,主要出现在将字符串解析成数字出错的场合
但是NaN
是属于Number
类型的
typeof NaN // "numbe"
5 - 'x' // NaN
0 / 0 // NaN
Math.acos(2) // NaN
Math.log(-1) // NaN
Math.sqrt(-1) // NaN
NaN
不等于任何值,包括它本身
NaN
的布尔值为false
NaN
的任何运算都是NaN
NaN === NaN // false
Boolean(NaN) // false
NaN + 32 // NaN
NaN - 32 // NaN
NaN * 32 // NaN
NaN / 32 // NaN
2.3.3 Infinity
表示无穷,有正负之分
在数值太大或者非0数除以0时,都会得到Infinity
Math.pow(2, 1024) // Infinity
Infinity === -Infinity // false
1 / -0 // -Infinity
-1 / -0 // Infinity
Infinity
大于任何数,-Infinity
小于任何数,但与NaN
比较时总为false
Infinity > 1000 // true
-Infinity < -1000 // true
Infinity > NaN // false
-Infinity > NaN // false
Infinity < NaN // false
-Infinity < NaN // false
Infinity
的四则运算符合无穷的计算规则
3 字符串(string)
3.1 概述
字符串就是0个或多个排在一起的字符,并用单引号或双引号包起来
单引号字符串内部可以用双引号,双引号字符串内部可以用单引号
单/双引号内部使用单/双引号,必须在内部单/双引号前面加反斜杠,用于转义
'key = "value"'
"It's a long journey"
'Did she say \'Hello\'?'
"Did she say \"Hello\"?"
字符串默认只能写在一行,分成多行会出错
如果需要分行,可以在每一行的尾部使用反斜杠
连接运算符(+)也可以连接单行字符串,组成多行字符串
'a
b
c'
// SyntaxError: Unexpected token ILLEGAL
var longString = 'Long \
long \
long \
string';
// "Long long long string"
var longString = 'Long '
+ 'long '
+ 'long '
+ 'string';
// "Long long long string"
3.2 转义
反斜杠(\)在字符串内有特殊含义,用来表示一些特殊字符,所以又称为转义符
\0 :null(\u0000)
\b :后退键(\u0008)
\f :换页符(\u000C)
\n :换行符(\u000A)
\r :回车键(\u000D)
\t :制表符(\u0009)
\v :垂直制表符(\u000B)
' :单引号(\u0027)
" :双引号(\u0022)
\ :反斜杠(\u005C)
console.log('1\n2')
// 1
// 2
反斜杠还有三种特殊用法
(1)\HHH
反斜杠后面紧跟三个八进制数(000到377),代表一个字符。HHH对应该字符的Unicode码点,比如\251表示版权符号。显然,这种方法只能输出256种字符
(2)\xHH
\x后面紧跟两个十六进制数(00到FF),代表一个字符。HH对应该字符的Unicode码点,比如\xA9表示版权符号。这种方法也只能输出256种字符
(3)\uXXXX
\u后面紧跟四个十六进制数(0000到FFFF),代表一个字符。XXXX对应该字符的Unicode码点,比如\u00A9表示版权符号
'\251' // "©"
'\xA9' // "©"
'\u00A9' // "©"
'\172' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true
如果在非特殊字符前面使用反斜杠,则反斜杠会被省略
'\a' // "a"
3.3 字符串与数组
字符串可以当做数组来看,可以使用数组的方式返回字符、字符串长度,但无法更改
var s = 'hello';
s[0] // "h"
s[1] // "e"
s[4] // "o"
// 直接对字符串使用方括号运算符
'hello'[1] // "e"
s[6] // undefined
s[-1] // undefined
s['x'] // undefined
delete s[0];
s // "hello"
s[1] = 'a';
s // "hello"
s.length // 5
s.length = 3;
s.length // 5
3.4 字符的储存
字符在JavaScript中是以Unicode的形式储存的,并允许在程序中直接用Unicode码点表示字符,解析的时候会自动识别Unicode码,并转换成对应字符
字符在JavaScript中是以16位(2字节)储存的,但是随着Unicode收集的字符越来越多,出现了4字节的字符。但由于历史原因,JavaScript无法识别4字节的字符,会认为是两个2字节的字符,但浏览器可正常识别
var s = '\u00A9';
s // "©"
var f\u006F\u006F = 'abc';
foo // "abc"
''.length // 2
3.5 Base64转码
Base64 就是一种编码方法,可以将任意值转成 0~9、A~Z、a-z、+和/这64个字符组成的可打印字符。避免出现特殊字符,简化程序处理
btoa():任意值转为 Base64 编码
atob():Base64 编码转为原来的值
但如果是非ASCII得字符,就要增加一个转码环节
btoa(encodeURIComponent(str))
decodeURIComponent(atob(str)
4 布尔值(Boolean)
布尔值代表“真”和“假”,用true
和false
表示
在进行下列计算时,会返回一个布尔值
两元逻辑运算符:
&&
(And),||
(Or)
前置逻辑运算符:!
(Not)
相等运算符:===
,!==
,==
,!=
比较运算符:>
,>=
,<
,<=
以下值的布尔值为false
undefined
null
false
0
NaN
""或''(空字符串)
其他值的布尔值都为true
5 null和undefined
null
和undefined
都表示没有,几乎没有区别,但null
转为数字时等于0
,undefined
转为数字时等于NaN
Number(null) // 0
Number(undefined) // NaN
在平时程序书写时,如果想定义一个对象(object),但目前不想赋值,推荐赋值为null
。如果定义一个非对象的值,推荐使用undefined
var o = {p:null}; //o.p=null
var s; //s=undefined
6 对象(object)
对象(object)是一种重要的数据类型
6.1 概述
对象是由一组组“键-值”组成的
var obj = {
key: value,
key: value,
key: value
}
对象所有的键名都是字符串,数字会自动转为字符串
如果键名不符合标识名的条件(比如第一个字符为数字,或者含有空格或运算符),且不是数字,那么必须加引号
var obj = {
1: value,
3.2: value,
1e2: value,
.234: value,
0xFF: value,
1p: value,//error
'1p': value,
'h w': value,
'p+q': value
};
对象的value
可以是任何一种数据类型,甚至可以是自己
var obj;
obj = {
name: 'yyzcl',
age: 8,
self: obj
}
JavaScript允许属性后绑定,先定义看空对象,后面再赋值
var obj = {};
obj.name='yyzcl';
obj //{name: 'yyzcl'}
JavaScript 规定,如果行首是大括号,一律解释为语句(即代码块)。如果要解释为表达式(即对象),必须在大括号前加上圆括号
{ foo: 123 } //语句
({ foo: 123}) //对象
6.2 对象的引用
如果不同的变量名指向同一个对象,那么它们都是这个对象的引用
也就是说对象其实是储存在一个内存地址中,不同的变量都是对这个内存地址的引用,修改其中一个变量,就是在修改内存地址中的真实对象,那么其他引用这个内存地址中对象的变量也会改变
var obj1 = {};
var obj2 = obj1;
obj1.a = 1;
obj2.a // 1
obj2.b = 2;
obj1.b // 2
如果一个对象变量取消了对对象的引用,不影响其他变量对这个对象的引用
var obj1 = {};
var obj2 = obj1;
obj1=1;
obj2 //{}
6.3 对象的操作
6.3.1 读取/赋值
读取、赋值对象属性有两种方法,一个是点运算符,一个是方括号运算符
注意-如果使用方括号,键名必须加引号,不然会当变量处理
var obj = {
name: 'yyzcl',
yyzcl: 'ok'
};
var name='yyzcl';
obj.name // "yyzcl"
obj['name'] // "yyzcl"
obj[name] //"ok"
数字键名可以不加引号,会自动转为字符串,且数字键名只能用方括号运算符
6.3.2 delete与undefined
delete
可用于删除对象的属性,key
和value
都会被删除
使用undefined
只会操作value
var obj = {
name: 'yyzcl',
yyzcl: 'ok'
};
delete obj.name;
obj //{yyzcl: 'ok'}
obj.yyzcl = undefined;
obj //{yyzcl: undefined}
6.3.3 in运算符
in
可检查对象是否包含某个属性(检查的是键名,不是键值)
var obj = {
name: 'yyzcl'
};
'name' in obj //true
'yyzcl' in obj //false
in
无法识别自身属性和继承属性,对继承属性也会返回true
var obj = {
name: 'yyzcl'
};
'toString' in obj // true
6.3.4 for...in循环
for...in
循环用来遍历一个对象,遍历的是key
var obj = {
name: 'yyzcl',
age: 8,
yyzcl: 'ok'
};
for (var k in obj) {
console.log(obj[k]);
}
注意-键名遍历的顺序不一定和对象定义的一样
for...in循环有两个使用注意点
它遍历的是对象所有可遍历(enumerable)的属性,会跳过不可遍历的属性
它不仅遍历对象自身的属性,还遍历继承的属性
7 typeof
typeof
运算符可以返回一个值的数据类型
数值 - number
字符串 - string
布尔值 - boolean
undefined - undefined
对象 - object
函数 - function
null - object
后两个是JavaScript的特殊之处