变量类型和计算
1. typeof 能判断那些类型
2. 何时使用=== 何时使用==
3. 值类型和引用类型的区别
题目:手写深拷贝
知识点:变量类型和变量计算
变量类型:
值类型vs 引用数据类型
typeof运算符
深拷贝
值类型
let a = 100;
let b = a;
a=200;
console.log(b) // 100
//a和b互不干涉 a就是a b就是b 修改a的值b也不会改
引用类型
let a = { age:20 };
let b = a
b.age = 21
console.log(a.age) // 21
//就是说a等于的对象是一个内存地址,而a给了b的值就是一个内存地址,然后我修改了a的age变成21 b也是拿着这个地址,所以b的age也被修改了
深入分析:
值类型
在代码中会有一个栈,所有的值类型都在栈中存储
引用类型
代码除了栈还有个堆,这时候栈里边不会是存一个内存对象,内存对象存到了堆里,然后再栈的value里是一个在堆内存的内存地址。
常见的值类型
const a; //undefined
//这个要用let,如果用const 的话会报错
const s = "abc"; //String
const n = 100;// number
const b = true;
const s = Symbol("s");
常见的引用类型
const obj ={ x:100 } //对象
const arr =["a","b","c"]//数组
const n = null // 特殊引用数据类型,指针指向为空地址
function(){} //特殊引用数据类型,但不用于存储数据,所以没有拷贝,复制函数这一说
typeof运算符
1. 识别所有的值类型
2. 识别函数
3. 判断是否是引用数据类型(没有细分,基本都是返回object)
判断所有的值类型
let a; typeof a //undefined
const str = "abc"; typeof str //string
const n = 100; typeof n // number
const b = true; typeof b //boolean
const s = Symbol("s"); typeof s //symbol
手写递归函数
const obj1 = {
age: 10,
name: "xxx",
address: {
city: "beijing",
},
arr: ["a", "b", "c"],
};
const obj2 = deepClone(obj1);
obj1.address.city = "shanghai";
console.log(obj2.address.city);
console.log(obj1.address.city);
/**
*
* @param {Object} obj 要拷贝的对象
*/
function deepClone(obj = {}) {
if (typeof obj !== "object" || obj == null) {
// obj是null 或者是 不是对象或者数组,这时候直接返回obj就行了
return obj;
}
// 初始化返回结果
let result;
// 判断是不是数组还是对象
if (obj instanceof Array) {
result = [];
} else {
result = {};
}
for (let key in obj) {
// hasOwnProperty 保证 key 不是原型的属性
if (obj.hasOwnProperty(key)) {
// 递归调用
result[key] = deepClone(obj[key]);
}
}
// 返回结果
return result;
}
运行流程,细说递归,所谓递归就是代码结束返回值是自身调用
上方代码obj1.age是个基本类型所以在判断是否是基本数据类型的时候就直接返回了,obj1.name也是个基本数据类型所以也返回了,到了address时候这个是引用数据类型他就不会走判断基本数据类型内部的代码,然后继续往后走到了判断是数组还是对象(这里要说instanceof是可以判断引用数据类型的他的返回值是一个boolean)这里返回false所以判断是个对象,然后for循环这里循环是对象里的值,每个值需要判断一下保证每个key值都不是原型属性,然后上方定义的result赋值递归调用自身deepClone,传obj[key],这时候再执行一遍deepClone的函数流程到了这里是执行的address.city他是基本数据类型,在判断基础数据类型的时候,直接返回了obj,如果这里还是一个对象比如:
address:{
city:{
a:{
s:{
z:shanghai
}
}
}
}
这时候还是一个对象再此判断是数组还是对象,然后for循环每个key值,以此类推,知道拿到z直接返回基本数据类型,完成深拷贝