JS 数据类型和运算符

253 阅读6分钟

如何存数字

十进制转二进制即可

10 转 2

31 变成二进制,将图中?填上

image.png

经过一番尝试

image.png

所以 31(十进制) = 01 1111(二进制)

不是套公式吗?程序员从来不套公式

2 转 10

100011 变成十进制 每一位乘以 2 的 N 次方,然后加起来即可 100011 = 2^5 + 2^1 + 2^0 = 35

用十六进制表示二进制

  • 为什么用十六进制
  • 因为二进制写起来太慢了:011110001011010
  • 记住 8 4 2 1 对应 X X X X
  • 从右往左每四位改写成一位: 011110001011010
  • 得到 3,12,5,10;把大于9的数字改为ABCDEF
  • 于是得到 3C5A,你也可以用计算器的程序员模式
  • HEX 表示 16 进制,BIN 表示 2 进制
  • OCT 表示 8 进制,DEC 表示 10 进制

image.png

如何存字符

用 0~127 表示所有符号

重点记:0——48、A——65、a——97

image.png

GB2312

中国国家标准局来编,名称为「国标2312」

用 0000~FFFF 表示汉字

  • 一个16进制数是4个0/1位
  • FFFF就是4x4=16位,也就是两个字节
  • 最多收录 2^16 = 65536 个字符
  • 但只收录了 6000 多汉字、西文字母和日文假名
  • 「你」的 GB2312 编号为 C4E3
  • 「牛」的 GB2312 编号为 C5A3 image.png

GBK

微软推出了一个国标扩展,简称GBK

含21886个汉字和图形符号,收录了中日韩使用的几乎所有汉字,完全兼容 GB2312,依然使用 16 位(两字节)

后来国标局推出 GB18030 取代 GBK,GB18030 不兼容 GB2312

image.png

Unicode

万国码

优点

已收录 13 万字符(大于 16 位),全世界通用,以后还会继续扩充,不会停止,最新版只添加了一个字——令和的合体字

缺点

两个字节不够用,每个字符要用三个及以上字节,这样所有文件都扩大 50%,不划算,那怎么办?

UTF-8

用 Unicode,但存的时候偷懒

  • 存储「a 」
  • a 对应的 Unicode 编号为 97,十六进制为 61
  • Unicode 直接存: 0000000000000000‭01100001‬
  • UTF-8偷懒存法: 01100001
  • 三字节变一字节,比GBK 还省
  • 存储「你」
  • 你对应的 Unicode 编号为 4F60
  • Unicode 直接存: 00000000‭0100111101100000‬
  • UTF-8偷懒存法: ‭111001001011110110100000‬
  • 还是三字节,没有省,但是字母都能省一点
  • UTF-8 中的 8 的意思是
  • 最少可用 8 位存一个字符

UTF-8 的规则

  • 以「你a」为例
  • 11100100101111011010000001100001
  • 如何知道上述内容表示什么字符?
  • 读 8 位信息 11100100
  • 发现开头有 3 个 1,说明这个字符有 3 个八位
  • 于是再读两个 8 位信息 10111101 10100000
  • 前面的 10 不要,其他合起来,得 0100111101100000
  • 这就还原为 Unicode 的你了:
  • 000000000100111101100000
  • 再读 8 为信息 01100001
  • 发现开头是 0,说明这个字符只占 8 位
  • 这就还原味 Unicode 的 a 了:
  • 000000000000000001100001

JS 中的数据类型

8种(大小写无所谓)

  1. 数字 number
  2. 字符串 string
  3. 布尔 bool
  4. 符号 symbol
  5. 任意大的整数 bigint
  6. 空 undefined
  7. 空 null
  8. 对象 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数字的存储形式

  • 浮点就是浮动的点,意思就是小数点会乱动
  • 123.456 可以表示为 1.23456e10^2,也可以表示为 12345.6e10^-2

image.png 64位存储一个 number

  • 符号占 1 位
  • 指数占 11 位(-1023~1024)
  • 有效数字占 52 位(开头的 1 省略)

范围和精度

范围(忽略符号位)

  • 指数拉满、有效数字拉满,得到最大二进制数字
  • Number.MAX_VALUE: 1.7976931348623157e+308
  • 指数负方向拉满、有效数字最小1,得到最小值
  • Number.MIN_VALUE: 5e-324 精度(有效数字)
  • 最多只能到52+1个二进制位表示有效数字
  • 2^53 对应的十进制是 9 后面 15 个零
  • 所以15位有效数字都能精确表示
  • 16位有效数字如果小于 90 开头,也能精确表示
  • 9110000000000001 就存不下来

字符串 string

每个字符两个字节

  • 单引号:'你好'
  • 双引号:"你好"
  • 反引号:你好 如果你想要在字符串里回车
let s = `这样是
可以的
用反引号很容易做到`

字符串的属性

1、string.length

'123'.length     // 3
'\n\r\t'.length  // 3
''.length        // 0
' '.length       // 1

通过下标读取字符:string[index]

let s = 'hello';
s[0] // "h"
s[5] // undefined,居然不报错

base64 转码

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

布尔 boolean

true 和 false,注意大小写

下列运算符会得到 bool 值

  • 否定运算: !value
  • 相等运算: 1 == 2、1 != 2、3 === 4、3 !== 4
  • 比较运算: 1 > 2、1 >= 2、3 < 4、3 <= 4

if 配 bool

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

问题来了,如果 value 是 bool 值还好说,如果 value 不是 bool 值咋办,谁真谁假

  • 1 是真还是假,0 是真还是假
  • '1' 是真还是假,'0' 是真还是假

五个 falsy 值

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

分别是 undefined、 null、 0、 NaN 、''

因此:

  • 1 是真,0 是假
  • '1' 是真,'0' 是真

undefined 和 null

区别:

两种空类型,没有本质区别

细节一: 如果一个变量声明了,但没有赋值,那么默认值就是 undefined,而不是 null

细节二: 如果一个函数,没有写 return,那么默认 return undefined,而不是 null

细节三: 前端程序员习惯上,把非对象的空值写为 undefined,把对象的空值写为 null, 但仅仅是习惯上而已

Symbol

推荐阅读: 方应杭:每日一题」JS 中的 Symbol 是什么?

变量声明

三种声明方式

  • var a = 1
  • let a = 1
  • const a = 1 区别:
  • var 是过时的、不好用的方式
  • let 是新的,更合理的方式
  • const 是声明时必须赋值,且不能再改的方式

let声明

规则

  • 遵循块作用域,即使用范围不能超出 { }
  • 不能重复申明
  • 可以赋值,也可以不赋值
  • 必须先声明再使用,否则报错
  • 全局声明的 let 变量,不会变成 window 的属性
  • for 循环配合 let 有奇效

const 声明

规则:

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

指定值同时也指定了类型:

  • let a = 1
  • 但是值和类型都可以随意变化
  • a = 2
  • a = '字符串'

类型转换

number => string

  • String(n)
  • n + ''

string => number

  • Number(s)
  • parseInt(s) / parseFloat(s)
  • s - 0
  • +s

x => bool

  • Boolean(x)
  • !!x

x => string

  • String(x)
  • x.toString()