Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript的数据类型 #2

Open
yyzclyang opened this issue May 12, 2018 · 0 comments
Open

JavaScript的数据类型 #2

yyzclyang opened this issue May 12, 2018 · 0 comments

Comments

@yyzclyang
Copy link
Owner

yyzclyang commented May 12, 2018

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位:数值的小数部分

2.1.1 符号位

表示数值的正负,0为正,1为负

2.1.2 指数部分

指数部分共有11位,所以其最大值为(2047),但是指数要分正负,所以引入了一个偏差值(Bias),为-1023。指数部分储存的数全是正数,但加上偏差值,就有了负数部分。比如:指数部分是00000000000的话,计算机加上偏差值之后最终结果就变成了-1023,就能表示负的指数了。

指数部分的最终能表示[-1023,1024],那么一个64位浮点数能表示的数值为,不包括

如果一个数大于,那么就会发生“正向溢出”,即无法表示,返回Infinity
如果一个数小于(利用指数部分能表示的最小值是,加上64位浮点数小数部分的52位,共75位),那么就会发生“负向溢出”,无法表示,返回0

注:chrome可以表示,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的特殊之处

@yyzclyang yyzclyang changed the title 2018.05.12 JavaScript的数据类型 JavaScript的数据类型 Aug 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant