JS数据类型

227 阅读5分钟

数字与字符串

  • 都是一,为什么要分 1 和 '1'

  • 功能不同

  1. 数字是数字,字符串是字符串,要严谨
  2. 数字能加减乘除,字符串不行
  3. 字符串能表示电话号码,数字不行
  • 存储形式不同
  1. JS 中,数字是用 64 位浮点数的形式存储的
  2. JS 中,字符串是用类似 UTF8 形式存储的(UCS-2)

如何存数字

十进制转二进制即可

二进制

  • 10 转 2 31 变成二进制: image.png 经过一番尝试: image.png 所以 31(十进制) = 01 1111(二进制)
  • 2 转 10 100011 变成十进制 每一位乘以 2 的 N 次方,然后加起来即可

100011 = 2^5 + 2^1 + 2^0 = 35

用十六进制表示二进制

  • 什么用十六进制? 因为二进制写起来太慢了: 011 1100 0101 1010
记住 2^3    2^2    2^1    2^0 
对应  X      X      X      X

从右往左每四位改写成一位: 

     011 1100 0101 1010
得到  3,  12,   5,   10

把大于9的数字改为ABCDEF

0 1 2 3 4 5 6 7 8 9 A B C D E F
  
于是得到 3C5A,

你也可以用计算器的程序员模式

HEX 表示 16 进制,BIN 表示 2 进制

OCT 表示 8 进制,DEC 表示 10 进制

如何存字符?

转成数字就ok,但是注意,'1' 不能用1来表示

如何存储abc123?

用编号表示,0~127表示所有符号,如: 0用48表示; a用97表示; A用65表示;

JS 中的数据类型

  • 7种(大小写无所谓)
  1. 数字 number
  2. 字符串 string
  3. 布尔 bool
  4. 符号 symbol
  5. 空 undefined
  6. 空 null
  7. 对象 object(只有 object 叫做复杂类型,其他都是简单类型

总结:四基两空一对象

  • 以下不是数据类型 数组、函数、日期, 它们都属于 object

数字 number(64位浮点数)

  • 整数写法: 1
  • 小数写法: 0.1
  • 科学计数法: 1.23e4
  • 八进制写法(用得少): 0123 或 00123 或 0o123
  • 十六进制写法: 0x3F 或 0X3F
  • 二进制写法: 0b11 或 0B11

特殊值

  • 正0 和 负0 都等于 0,要严谨
  • 无穷大 Infinity 、+Infinity 、-Infinity
  • 无法表示的数字 NaN (Not a Number) 但它是一个数字

64位浮点数

JS的number全都是以浮点数的形式存储的,没有单独的整数

  • JS数字的存储形式

浮点就是浮动的点,意思就是小数点会乱动

123.456 可以表示为 1.23456e10^2

也可以表示为 12345.6e10^-2 image.png

  • 64位存储一个number 符号占 1 位

指数占 11 位(-1023~1024)

有效数字占 52 位(开头的 1. 省略)

例: image.png

范围和精度

  • 范围(忽略符号位)
  1. 指数拉满、有效数字拉满,得到最大二进制数字 Number.MAX_VALUE: 1.7976931348623157e+308

  2. 指数负方向拉满、有效数字最小1,得到最小值 Number.MIN_VALUE: 5e-324

  • 精度(有效数字)
  1. 最多只能到52 + 1 个二进制位表示有效数字(+1表示开头的1.···种的1.)
  2. 2^53 对应的十进制是 9 后面 15 个零,所以15位有效数字都能精确表示
  3. 16位有效数字如果小于 90 开头,也能精确表示,9110000000000001 就存不下来

字符串 string

每个字符两个字节(阉割版 UTF8)

  • 写法:
  1. 单引号 '你好'

  2. 双引号 "你好"

  3. 反引号 `你好`

转义

  • 注意! 引号不属于字符串的一部分,就像书名号不属于书名的一部分一样

如果要在单引号里面包含单引号怎么办?

  • 错误写法
'it's ok' 
//JS 引擎会认为 'it' 就结束了,后面的看不懂
  • 正确写法
'it\'s ok'  // 用\挡住就可以了,这就是转义
"it's ok"
`it's ok`
//外面的符号和里面的不能一样,一样的话只能用\转义
  • 用另一种写法表示你想要的东西
\' 表示 '
\" 表示 "
\n 表示换行
\r 表示回车
\t 表示 tab 制表符
\\ 表示1个 \
\uFFFF 表示对应的 Unicode 字符
\xFF 表示前 256Unicode 字符

多行字符串

如果你想要在字符串里回车

let s = `这样是
可以的
用反引号很容易做到`

字符串的属性

  • 字符串的长度,string.length
'123'.length     // 3
'\n\r\t'.length  // 3,\n、\r、\t分别代表3个字符
'\\\\\\'.length  // 3,2个\等于1个\
''.length        // 0,空字符串
' '.length       // 1,空格字符串

通过下标读取字符

  • string[index]
let s = 'hello';
s[0] // "h"
  1. 注意 index 从 0 开始s[0] 是第一个字符
  2. 注意 index 到 length
let s = 'hello';
s[5] // undefined,居然不报错
s[4] // 'o'

base64 转码

  • window.btoa 正常字符串转为 Base64 编码的字符串

window.btoa('xxx')

  • window.atob Base64 编码的字符串转为原来的字符串
  • 一般用来隐藏招聘启事里的简历 邮箱:NzE1NzM0MTk5QHFxLmNvbQ==
  • 有时候也用来自欺欺人 所谓的「加密」,也就能骗过一部分外行

布尔 boolean(真或假)

  • 只有两个值 true 和 false,注意大小写
  • 下列运算符会得到 bool 值
  1. 否定运算 !value

  2. 相等运算

1 == 2
1 != 2
3 === 4
3 !== 4
  1. 比较运算
1 > 2
1 >= 2
3 < 4
3 <= 4

if 配 bool

  • if 语句常常需要判断真假
if( value ) {
      ... 
} else { ... }

如果 value 是 bool 值还好说

如果 value 不是 bool 值咋办,谁真谁假?

  • 1 是真还是假,0 是真还是假
  • '1' 是真还是假,'0' 是真还是假('1'、'0'都是真)

五个 falsy 值

falsy 就是相当于 false 但又不是 false 的值

分别是:

  • undefined
  • null
  • 0
  • NaN
  • '' 注意''不等于' '

补充:1&&2的值是2;0&&2的值是0(&&取第一个假值或最后一个值)

undefined 和 null 两种空类型

区别: 没有本质区别

  • 细节一 如果一个变量声明了,但没有赋值,那么默认值就是 undefined,而不是 null
  • 细节二 如果一个函数,没有写 return,那么默认 return undefined,而不是 null
  • 细节三 前端程序员习惯上,把非对象的空值写为 undefined,把对象的空值写为 null 但仅仅是习惯上而已

symbol 符号

不怎么常用

变量声明

  • 三种声明方式
var a = 1 
let a = 1 
const a = 1
a = 1
//这种情况下,a=1不是声明全局变量
function fn(){
    var a
function f2(){
    a = 1
}
    f2()
} fn()
//输出undefined
  • 区别
  1. var 是过时的、不好用的方式 (不要用var)
  2. let 是新的,更合理的方式
  3. const 是声明时必须赋值,且不能再改的方式
  4. 最后这种方式是错误的,不准这样声明

let 声明

  • 规则
  1. 遵循块作用域,即使用范围不能超出 { } 例:
{let b = 1
console.log(b)
}
console.log(b)
//第一个console输出1,第二个直接报错
  1. 不能重复申明
let a = 1
{let a = 2}
//这样声明是可以的

//不能let a = 1  再 let a = 2
因为,同一个作用域不能重复声明
  1. 可以赋值,也可以不赋值
let a
let a = 1
//二者皆可
  1. 必须先声明再使用,否则报错
{console.log(b)
 let b = 1}
//直接报错,因为不能先使用后声明
  1. 全局声明的 let 变量,不会变成 window 的属性
//但是var会,这是一个bug
var abc = 'abc'
window.abc       //输出'abc',所以别用var..
  1. for 循环配合 let 有奇效
for(let i = 0; i < 5; i++){
    setTimeout(() =>{console.log(i)})
    }
    //输出0,1,2,3,4

const 声明

  • 规则:跟 let 几乎一样
  • 只有一条不一样:声明时就要赋值赋值后不能改

变量声明

  • 指定值var a = 1
  • 同时也指定了类型var a = 1(类型是number)
  • 但是值和类型都可以随意变化
a = 2
a = '字符串'  //类型改为字符串

name 和 'name' 的区别

  • name 是变量 值可变,可能是 'name',也可能是 'hello'
  • 'name' 是字符串常量 常量就是不变量, 'name' 只能是 'name',不能是其他值

类型转换

  • number => string
let n = 1
String(n)   //得'1',但是太麻烦
n + ''      //'1',推荐!
  • string => number
let s = '1'
Number(s)                     // 1
parseInt(s) / parseFloat(s)   // 1
s - 0  /  +s                  //简单,推荐!
  • x => bool (x为任意类型)
let x = 1
Boolean(x)    //true
!!x           //true,推荐!
let a = 0
!!a           //false
  • x => string(x为任意类型)
String(x)
x.toString()

例:

true.toString()   //'true'

1.toString()      //不行,会报错,因为有bug

//要写成:
(1).toString1..toString1 .toString