Js的数据类型

109 阅读8分钟

Js的数据类型

number 数字 string 字符串 boolean 布尔 symbol 符号 nullundefinedobject 对象 bigint 表示任意大的整数

number

特殊值
  • 正0 和负0 都等于0,但是负0又不一样
  • 无穷大 Infinity+Infinity-Infinity
  • 无法表示的数字 NAN(not a number)
64位浮点数

JS数字的存储形式

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

114.514

  • 可以表示为1.14514e2
  • 也可以表示为11451.4e-2

符号占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

写法
  • 单引号'你好'
  • 双引号"你好"
  • 反引号 ``

注意 引号不属于字符串的一部分

转义

用另一种写法表示你想要的东西'表示'

  • \”表示 "
  • \n表示换行
  • \r表示回车
  • \t表示tab 制表
  • \表示 \
  • \uFFFF 表示对应的Unicode字符
  • \xFF 表示前256个Unicode字符
多行字符串

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

用反引号

let s =`这样是
        可以的
        用反引号很容易做到`
字符串的长度

string.length

'123'.length // 3
‘\n\r\t’.length // 3字节
''.length // 0
' '.length // 1
通过下标读取字符
string[index]let s = 'hello'; 
s[0]// "h"

index 从0开始 s[0]是第一个字符

超过这个字符的则会显示undefined

let s = 'hello' ;
s[5] // undefined,居然不报错 
s[4]// 'o'
base64转码

window.btoa

正常字符串转为Base64 编码的字符串

window .atob

Base64 编码的字符串转为原来的字符串

—般用来隐藏招聘启事里的简历邮箱

基本上也用来自欺欺人 所谓的「加密」,也就能骗过一部分外行

Boolean

只有truefalse

下列运算符会得到bool值

否定运算
  • ! value
相等运算
  • 1 == 2 (false)
  • 3 === 4(false)
  • 3 !== 4(true)
比较运算
  • 1 >2
  • 1 >= 2
  • 3 <4
  • 3 <= 4
五个falsy 值

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

  • undefined
  • null
  • NaN
  • ''
  • 0

ps''' '是不一样的,前者为空字符串,后者为空格

undefined 和 null的区别

区别 没有本质区别

细节一

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

细节二

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

细节三

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

symbol

symbol 是一种基本数据类型。Symbol() 函数会返回 symbol 类型的值,该类型具有静态属性和静态方法。它的静态属性会暴露几个内建的成员对象;它的静态方法会暴露全局的 symbol 注册,且类似于内建对象类,但作为构造函数来说它并不完整,因为它不支持语法:"new Symbol()"。

bigint

BigInt 是一种内置对象,它提供了一种方法来表示大于 2^53 - 1 的整数。这原本是 Javascript 中可以用 Number 表示的最大数字。BigInt 可以表示任意大的整数。

变量声明

三种声明方式
var a = 1
let a = 1 
const a = 1 
区别
  • var 是过时的、不好用的方式
  • let是新的,更合理的方式
  • const是声明时必须赋值,且不能再改的方式最后这种方式是错误的,不准这样声明
var声明
let 声明

规则

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

规则

前三条一样

  • 遵循块作用域,即使用范围不能超出{ }不能重复申明
  • 可以赋值,也可以不赋值、必须先声明再使用,否则报错
  • 全局声明的let变量,不会变成 window 的属性
  • 声明时就要赋值,赋值后不能改,如果是数组就可以添加数据后面在解释

指定值

var a = 1

同时也指定了类型

var a = 1

但是值和类型都可以随意变化

a = 2
a = '字符串'

类型转换

number =>string

  • String(n)
  • n+ 'i

string =>number

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

x=>bool

  • Boolean (x)
  • !!

x=>string

  • String(x)
  • x.toString()

Object

定义
  • 无序的数据集合
  • 键值对的集合
写法
let obj = { 'name': 'mike', 'age': 32 }
let obj = new Object({'name': 'mike','age': 32})
细节
  • 键名是字符串,不是标识符,可以包含任意字符
  • 引号可省略,省略之后就只能写标识符
  • 就算引号省略了,键名也还是字符串(大声!)
let obj = { key: value}

每个 key 都是对象的属性名(property)

每个 value 都是对象的属性值

  • 所有属性名会自动变成字符串
let obj = {
1: 'a',
3.2: 'b',
1e2: true,
1e-2: true,
234: true,
0xFF: true
};

Object.keys(obj)

=> ["1", "100", "255", "3.2", "0.01", "0.234"]

Object.keys(obj) 可以得到 obj 的所有 key

  • 除了自己写定的值作为属性名,变量也可以作为属性名
let ac = 'age'
let obj = { ac : '25'} //这样写,属性名为 'ac'
let obj = { [ac] : '18' } //这样写,属性名为 'age'
let obj = { [ac] : '18' } ====> let obj = { age : '18' } //当然,age也是字符串

对比

  1. 不加 [ ] 的属性名会自动变成字符串
  2. 加了 [ ] 则会当做变量求值
  3. 值如果不是字符串,则会自动变成字符串
对象的隐藏属性

隐藏属性

  • JS 中每一个对象都有一个隐藏属性
  • 这个隐藏属性储存着其共有属性组成的对象的地址
  • 这个共有属性组成的对象叫做原型
  • 也就是说,隐藏属性储存着原型的地址

代码示例

var obj = {}

obj.toString() // 居然不报错

因为 obj 的隐藏属性对应的对象上有 toString()

原型

每个对象都有原型

  • 原型里存着对象的共有属性
  • 比如 obj 的原型就是一个对象
  • obj.__proto__ 存着这个对象的地址
  • 这个对象里有 toString / constructor / valueOf 等属性

对象的原型也是对象

  • 所以对象的原型也有原型
  • obj = {} 的原型即为所有对象的原型
  • 这个原型包含所有对象的共有属性,是对象的根
  • 这个原型也有原型,是 null
对象的增删改查
删除属性

使用delete obj.xxxdelete obj['xxx']

即可删除 obj 的 xxx 属性

有一个问题是需要区分属性值为 undefined不含属性名

  • 不含属性名
'xxx' in obj === false
  • 含有属性名,但是值为 undefined
'xxx' in obj && obj.xxx === undefined
  • 注意 obj.xxx === undefined不能断定 'xxx' 是否为 obj 的属性
  • 举个例子

你有没有安装360?

A: 没有 // 不含属性名

B: 有,但是没有装(下载了安装包) // 含有属性名,但是值为 undefined

一定要分清楚,没有与undefined的区别

查看所有属性
  • 查看自身所有属性
Object.keys(obj)
  • 查看自身+共有属性
console.dir(obj)

或者自己依次用 Object.keys 打印出 obj.__proto__

判断一个属性是自身的还是共有的

obj.hasOwnProperty('toString')

ps

  • 'xxx' in obj表示这个属性是否在obj里面,也包含了原型中方法。
  • obj.hasOwnProperty('xxx')判断一个属性是自身的还是共有的,如果是自己的就会返回true,否则返回false(自己的原型上的方法或者原型链上的方法

两种方法查看属性

  1. 中括号语法:obj['key']
  1. 点语法:obj.key
  1. 坑新人语法:obj[key] 变量 key 值一般不为 'key'

请优先使用中括号语法

  • 点语法会误导你,让你以为 key 不是字符串
  • 等你确定不会弄混两种语法,再改用点语法

和之前都一样obj[name]不等于obj['name']

  • 第一个name是一个变量,取决于当前作用域的name对应的值(说不定还没有name的值呢)
  • 第二个name是obj本身的name
修改或增加属性

直接赋值

let obj = {name: 'mike'} // name 是字符串

obj.name = 'mike' // name 是字符串

obj['name'] = 'mike' 

obj[name] = 'mike' // 错,因 name 值不确定

obj['a'+'ge'] = 114

let key = 'name'; obj[key] = 'mike'

let key = 'name'; obj.key = 'mike' // 错

因为 obj.key 等价于 obj['key']

批量赋值

Object.assign(obj, {age: 18, gender: 'man'})

修改或增加共有属性

  • 无法通过自身修改或增加共有属性
let obj = {}, obj2 = {} // 共有 toString

obj.toString = 'xxx' //只会在改 obj 自身属性

obj2.toString //还是在原型上
  • 我偏要修改或增加原型上的属性

obj.__proto__.toString = 'xxx' // 不推荐用 __proto__

Object.prototype.toString = 'xxx' 一般来说,不要修改原型,会引起很多问题

修改隐藏属性

不推荐使用 __proto__

let obj = {name:'frank'}

let obj2 = {name: 'jack'}

let common = {kind: 'human'}

obj.__proto__ = common

obj2.__proto__ = common

推荐使用 Object.create

let obj = Object.create(common)

obj.name = 'frank'

let obj2 = Object.create(common)

obj2.name = 'jack'

最好不要改,如果要改,就一开始就改,别后来再改