众所周知 JavaScript(一下简称 Js) 是一门弱类型语言,变量的类型不够明确,不同类型之间可以相互赋值。
Js 的数据类型可以分为两大类:
![]()
1、基础数据类型
基础数据类型包含以下
中:
- Number
- String
- Boolean
- undefined
- null
- Symbol (es6 新增的一种基础数据类型)
1-1、Number
1-1-1、声明的几种方式:
// 字面量的形式声明
var num = 23
console.log(num) // 23
// 实例化的形式声明
var num = new Number(23)
console.log(num) // 23
1-1-2、Number 类型包含了 int、浮点数、科学记数法、八进制数和十六进制数及特殊的 Number 值
1-1-2-1、int
var num = 23
1-1-2-2、浮点数
var num = 23.5
1-1-2-3、科学记数法 E/e
var num = 1.5e12 // 表示1.5乘以10的7次方
var num = 1.5-e12 // 表示1.5除以10的7次方
1-1-2-4、八进制
已 0 开头,后面的数字为任意的 0-7
var num = 070 // 等于十进制的 56
转换规则:7 x + 7 x
= 56
1-1-2-5、十六进制
已 0x 开头,后面的数字为任意的 0-F (字母可以是大写的,也可以是小写的)
var num = 0x1f // 等于十进制的 31
转换规则:1 x + 15 x
= 31
尽管所有整数都可以表示为八进制或十六进制的字面量,但所有数学运算返回的都是十进制结果。
1-1-2-6、特殊的 Number 值
- Number.MAX_VALUE(Infinity) 和 Number.MIN_VALUE(-Infinity) 无穷大 和 无穷小 (可以对任何数调用 isFinite() 方法,以确保该数不是无穷大)
- NaN 表示非数(Not a Number)。一般说来,这种情况发生在类型(String、Boolean 等)转换失败时。
console.log(NaN == NaN) // false
console.log(NaN === NaN) // false
console.log(isNaN(NaN)) // true
console.log(isNaN(6)) // false
1-2、String
1-2-3、声明方式
// 字面量的形式声明
var str = 'hello'
console.log(str) // hello
// 实例化的形式声明
var str = new String("hello")
console.log(str) // hello


1-3、Boolean
// 字面量的形式声明
var flag = false
console.log(flag) // false
// 实例化的形式声明
var flag = new Boolean(false)
console.log(flag) // false
注意:
1-4、undefined
Undefined 类型只有一个值,即 undefined。
1-4-1、声明
var num
console.log(num)
1-4-2、另外几种值为 undefined 的情况
- 通过点语法访问的时候(对象属性)
- 通过下标访问的时候(数组)
- 不指定函数的返回值时
var oTemp;
alert(typeof oTemp); //输出 "undefined"
alert(typeof oTemp2); //输出 "undefined"

前面的代码对两个变量输出的都是 "undefined",即使只有变量 oTemp2 从未被声明过。如果对 oTemp2 使用除 typeof 之外的其他运算符的话,会引起错误,因为其他运算符只能用于已声明的变量上。
1-5、null
null 类型只有一个值,即 null。
console.log(null == undefined) // true
console.log(null === undefined) // false
console.log(null == null) // true
console.log(null == null) // true
1-5、Symbol
Symbol 是 es6 新增的一种基础数据类型,是用来描述一个
的值。 Symbol(query: any): symbol query 对当前 Symbol 的描述,便于代码的阅读
1-5-1、声明方式
var symbol1 = Symbol('symbol')
var symbol2 = Symbol('symbol')
console.log(symbol1 === symbol2) // false
console.log(symbol1 === symbol2) // false
1-5-2、用处
- 可以用来声明一个常量
- 可以用做对象的属性,但是不能被for-in, Object.keys()等访问到,也就是不可枚举的
- 使用Symbol定义类的私有属性/方法
2、引用数据类型
引用数据类型包含以下
中:
- Object 对象
- String 对象
- Boolean 对象
- Number 对象
3、如何判断基础数据类型与引用数据类型之间
3-1、基础数据类型可以通过 typeof 来判断
var num = 12
console.log(typeof num) // number
var str = 'hello'
console.log(typeof str) // string
var flag = true
console.log(typeof flag) // boolean
var un
console.log(typeof un) // undefined
var nul = null
console.log(typeof nul) // object
var fun = function () {}
console.log(typeof fun) // function
var obj = new Object()
console.log(typeof obj) // object
var arr = [1, 2]
console.log(typeof obj) // object
由上可知:
3-2、引用数据类型可以通过 instanceof 来判断 (实现原理是通过原型链)
var obj = new Object()
console.log(obj instanceof Object) // true
var str = new String('hello')
console.log(str instanceof String) // true
var arr = [1, 2]
console.log(arr instanceof Array) // true
var num = 1
console.log(num instanceof Number) // false
总结:
4、基础数据类型与引用数据类型之间的区别
4-1、 基础数据类型与引用数据类型之间的区别主要体现在在内存中的存储。
我们先来看一个例子,思考一下答案是什么
var num1 = 10
var num2 = num1
num2 = 20
console.log(num1, num2)
var person1 = {name: 'Tom'}
var person2 = person1
person2.name = "Kail"
console.log(person1, person2)
答案:
10 20
{name: 'Kail'} {name: 'Kail'}
可以看出 num1 不会受到 num2 的影响,person1 会受到 person2 的影响。

总结:
4-2、浅拷贝、深拷贝
浅拷贝、深拷贝的出现就是为了解决引用数据类型赋值时,产生相互影响的问题
4-2-1、浅拷贝
浅拷贝
还是不能彻底解决多层引用数据类型之间的嵌套。
var person1 = {name: 'Tom'}
var person2 = Object.assign({}, person1)
person2.name = "Kail"
console.log(person1, person2) // {name: "Tom"} {name: "Kail"}
var person1 = {targe: {name: 'Tom'}}
var person2 = Object.assign({}, person1)
person2.targe.name = "Kail"
console.log(person1, person2) // {targe: {name: 'Kail'}} {targe: {name: 'Kail'}}
4-2-2、深拷贝
深拷贝跟层级无关
var person1 = {name: 'Tom'}
var person2 = JSON.parse(JSON.stringify(person1))
person2.name = "Kail"
console.log(person1, person2) // {name: "Tom"} {name: "Kail"}
var person1 = {targe: {name: 'Tom'}}
var person2 = JSON.parse(JSON.stringify(person1))
person2.targe.name = "Kail"
console.log(person1, person2) // {targe: {name: 'Tom'}} {targe: {name: 'Kail'}}
5、类型之间的转换
5-1、 + (字符串连接符,加号运算符)只要有一边为字符串或者为引用数据类型时另外一边就必须转换为字符串才可以做运算;只有两边都是纯数字时才做加法
var log = console.log
log(1 + 2) // 3
log(1 + '2') // '12'
log(1 + true) // 2
log('1' + true) // '1true'
log('1' + undefined) // '1undefined'
log(1 + undefined) // NaN
log('1' + null) // '1null'
log(1 + null) // 1
log(1 + []) // '1'
log(1 + [2]) // '12'
log(1 + [2, 3]) // '12,3'
log(1 + [{count: 2}]) // '1[object Object]'
log(1 + [{count: 2}, 2, true]) // '1[object Object],2,true'
log(1 + {}) // '1[object Object]'
log(1 + {count: 2}) // '1[object Object]'
分析:
1、undefined 转换成数字时为 NaN
2、null 转换成数字时为 0
3、空数组转换为空字符串
4、非空数组转换为字符串,按照每个元素来转换成字符串,然后将其结果以逗号的形式拼接起来
5、对象转换成字符串都为 '[object Object]'
5-2、 算术运算符(除 + 之外),都会将两边转换成数字来运算,
var log = console.log
log(2 * 2) // 4
log(2 * '2') // 4
log('2' * '2') // 4
log(2 * null) // 0
log(2 * undefined) // NaN
log(2 * [1]) // 2
log(2 * [1, 2]) // NaN
log(2 * {a: 1}) // NaN
log(2 / 2) // 1
log(2 / '2') // 1
log(2 / null) // Infinity
log(2 / undefined) // NaN
log(2 / [1]) // 2
log(2 / [1, 2]) // NaN
log(2 / {a: 1}) // NaN
5-3、 比较运算符,都会将两边转换成数字来运算,(当两边为字符串时除外,此时会利用字符的 Unicode 编码来比较大小),特殊情况(如下)
log(2 > 2) // false
log(2 > '1') // true
log(2 > null) // true
log(2 > [1]) // true
log(2 > {a: 1}) // false
log('a' > 2) // false
log('abc' < 'b') // true
// 特殊情况
log(undefined == undefined) // true
log(undefined === undefined) // true
log(null == null) // true
log(null === null) // true
log(undefined == null) // true
log(undefined === null) // false
log(NaN == NaN) // false
log(NaN === NaN) // false
5-4、 逻辑非隐式转换与关系运算符隐式转换搞混淆
log([] == 0) // true [].valueOf().toString = '' Number('') = 0
log(![] == 0) // true ![] = false Number(false) = 0
log([] == []) // false 地址不一样
log(![] == []) // true ![] = false Number(false) = 0 [].valueOf().toString = '' Number('') = 0
log(!{} == {}) // false !{} = false Number(false) = 0 {}.valueOf().toString = '[object Object]' Number('[object Object]') = NaN
log({} == {}) // false 地址不一样
5-4、类型转换总结表
| type | Number | String | Boolean |
|---|---|---|---|
| Number | 原值转换 | 原值转换 | 1: 0-> false -0 -> false 2: 其它数值都为true |
| String | 1: 全部由数字组成的字符串,正常转换; 2: 空字符串为0; 3: 其它为NaN |
原值转换 | 1:空字符串为false; 2: 其它为true |
| Boolean | false -> 0 true -> 1 | 原值转换 | |
| null | 0 | '' | false |
| undefined | NaN | 原值转换 | false |
| Object | NaN | '[object Object]' | true |
| Array | 1:[] 转换为 0([].valueOf().toString() = '' Number('') = 0) 2: 只有一个元素时,就按这个元素的类型转换成 Number([undefined] 除外,转换为 0) 3: 其它情况为 NaN |
将每个元素转换成字符串以逗号的形式拼接 | true |
| function | NaN | 将函数直接变成字符串输出 | true |
| Symbol | var b = Symbol('测试类型转换') Number(b) Uncaught TypeError: Cannot convert a Symbol value to a number |
var b = Symbol('测试类型转换') String(b) "Symbol(测试类型转换)" |
true |
【随手笔记,感谢阅读,不对之处请指教,谢谢】