JavaScript的数据类型

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位,所以其最大值为<a href="https://www.codecogs.com/eqnedit.php?latex=2^{11}-1" target="_blank"><img src="https://latex.codecogs.com/gif.latex?2^{11}-1" title="2^{11}-1" /></a>(2047),但是指数要分正负,所以引入了一个偏差值(Bias),为-1023。指数部分储存的数全是正数,但加上偏差值,就有了负数部分。比如:指数部分是00000000000的话,计算机加上偏差值之后最终结果就变成了-1023,就能表示负的指数了。

指数部分的最终能表示[-1023,1024],那么一个64位浮点数能表示的数值为<a href="https://www.codecogs.com/eqnedit.php?latex=\pm&space;(2{-1023},2{1024})" target="_blank"><img src="https://latex.codecogs.com/gif.latex?\pm&space;(2{-1023},2{1024})" title="\pm (2{-1023},2{1024})" /></a>,不包括<a href="https://www.codecogs.com/eqnedit.php?latex=2^{-1023}" target="_blank"><img src="https://latex.codecogs.com/gif.latex?2^{-1023}" title="2^{-1023}" /></a>和<a href="https://www.codecogs.com/eqnedit.php?latex=2^{1024}" target="_blank"><img src="https://latex.codecogs.com/gif.latex?2^{1024}" title="2^{1024}" /></a>

如果一个数大于<a href="https://www.codecogs.com/eqnedit.php?latex=2^{1024}" target="_blank"><img src="https://latex.codecogs.com/gif.latex?2^{1024}" title="2^{1024}" /></a>,那么就会发生“正向溢出”,即无法表示,返回Infinity
如果一个数小于<a href="https://www.codecogs.com/eqnedit.php?latex=2^{-1075}" target="_blank"><img src="https://latex.codecogs.com/gif.latex?2^{-1075}" title="2^{-1075}" /></a>(利用指数部分能表示的最小值是<a href="https://www.codecogs.com/eqnedit.php?latex=2^{-1023}" target="_blank"><img src="https://latex.codecogs.com/gif.latex?2^{-1023}" title="2^{-1023}" /></a>,加上64位浮点数小数部分的52位,共75位),那么就会发生“负向溢出”,无法表示,返回0

注:chrome可以表示<a href="https://www.codecogs.com/eqnedit.php?latex=2^{-1075}" target="_blank"><img src="https://latex.codecogs.com/gif.latex?2^{-1075}" title="2^{-1075}" /></a>,IE不行,其他没测试

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)

布尔值代表“真”和“假”,用truefalse表示

在进行下列计算时,会返回一个布尔值

两元逻辑运算符: && (And),|| (Or)

前置逻辑运算符: ! (Not)

相等运算符:===!====!=

比较运算符:>>=<<=

以下值的布尔值为false

undefined
null
false
0
NaN
""或''(空字符串)

其他值的布尔值都为true

5 null和undefined

nullundefined都表示没有,几乎没有区别,但null转为数字时等于0undefined转为数字时等于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可用于删除对象的属性,keyvalue都会被删除

使用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的特殊之处

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容