值类型和引用类型
值类型
值类型示例
let a = 100
let b = a
a = 200
console.log(b)
值类型在内存中的存储方式
值类型一般都是在栈中存储一个值
栈 |
key |
value |
a |
100 |
... |
... |
常见值类型
let a
const s = 'abc'
const n = 100
const b = true
const s = Symbol('s')
引用类型
引用类型示例
let a = { age: 20 }
let b = a
b.age = 21
console.log(a.age)
引用类型在内存中的存储方式
变量在计算机中存储时,栈和堆是同时存在的,栈是从上至下累加,堆是从下至上累加。
引用类型会在堆中申请一个内存地址,将变量的值存储在堆里。
栈中存储的不在是一个值,而是对应堆的内存地址。
为什么引用类型不将值直接存储在栈中?原因还是性能问题,引用类型值的占用空间比值类型大的多,无论是存储还是引用,都会导致速度非常慢。
栈 |
key |
value |
a |
内存地址1 |
... |
... |
栈 |
key |
value |
a |
内存地址1 |
b |
内存地址1 |
栈 |
key |
value |
a |
内存地址1 |
b |
内存地址1 |
... |
... |
内存地址1 |
{age:20} |
key |
value |
堆 |
... |
... |
内存地址1 |
{age:20} |
key |
value |
堆 |
... |
... |
内存地址1 |
{age:21} |
key |
value |
堆 |
常见引用类型
const obj = { x: 100 }
const arr = ['a','b', 'c']
const n = null
function fn() {}
typeof和深拷贝
判断所有值类型
typeof a;
typeof "100";
typeof 100;
typeof true;
typeof Symbol("s");
typeof console.log();
typeof function fn() {};
typeof null;
typeof ["a", "b"];
typeof { x: 100 };
深拷贝
深拷贝步骤:
- 先判断值类型是否为数组或对象,如果不是则直接返回被拷贝的值。
- 初始化返回结果,如果引用类型是数组则此次拷贝返回一个数组,如果是对象则返回一个对象。
- 遍历引用类型的key,保证key不是原型上的属性.
- 对遍历的值进行递归拷贝。
function deepClone(obj = {}) {
if (typeof obj !== "object" || obj == null) {
return obj;
}
let result;
if (obj instanceof Array) {
result = [];
} else {
result = {};
}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = deepClone(obj[key])
}
}
return result;
}}
变量计算
字符串拼接
const a = 100 + 10
const b = 100 + '10'
const c = true + '10'
==运算符
== 会尝试将两边的值进行类型转换后使他们尽量相等
100 == '100'
0 == ''
0 == false
false == ''
null == undefined
const obj = { x: 100 }
if (obj.a == null ) {}
if (obj.a === null || obj.a === undefined) {}
if语句和逻辑运算
if语句
if语句判断的其实是truly变量和falsely变量
- truly变量:!!a === true的变量
- falsely变量:!!a === false的变量
const a = true
if (a) {
}
const b = 100
if (b) {
}
const c = ''
if (c) {
}
const d = null
if (d) {
}
let e
if (e) {
/ ...
}
逻辑运算
10 && 0
'' || 'abc'
!window.abc