1.深拷贝和浅拷贝
深拷贝和浅拷贝的区别:
1.浅拷贝:
将原对象或原数组的引用直接赋给新对象,新数组,新对象/数组只是原对象的一个引用
2.深拷贝:
创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”
为什么要使用深拷贝?
我们希望在改变新的数组(对象)的时候,不改变原数组(对象)
内存模型
JS内存空间分为栈(stack)、堆(heap)、池(一般也会归类为栈中)。 其中栈存放变量,堆存放复杂对象,池存放常量。
基本数据类型与栈内存
JS中的基础数据类型,这些值都有固定的大小,往往都保存在栈内存中(闭包除外),由系统自动分配存储空间。我们可以直接操作保存在栈内存空间的值,因此基础数据类型都是按值访问 。 基础数据类型:Number String Null Undefined Boolean
引用数据类型与堆内存
JS的引用数据类型,比如数组Array,它们值的大小是不固定的。引用数据类型的值是保存在堆内存中的对象。JS不允许直接访问堆内存中的位置,因此我们不能直接操作对象的堆内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。因此,引用类型的值都是按引用访问的。这里的引用,我们可以粗浅地理解为保存在栈内存中的一个地址,该地址与堆内存的实际值相关联。
2.原型与原型链
1、原型
每个函数都有一个prototype属性,被称为显示原型
每个实例对象都会有_ proto 属性,其被称为隐式原型
每一个实例对象的隐式原型 proto _属性指向自身构造函数的显式原型prototype
2、constructor
每个prototype原型都有一个constructor属性,指向它关联的构造函数。
3、原型链
获取对象属性时,如果对象本身没有这个属性,那就会去他的原型__proto__上去找,如果还查不到,就去找原型的原型,一直找到最顶层(Object.prototype)为止。Object.prototype对象也有__proto__属性值为null。
3、js数据类型校验
五种方法
typeof、instanceof、constructor、Object.prototype.toString.call()
1 .typeof
基本数据类型中:Number,String,Boolean,undefined 以及引用数据类型中Function ,可以使用typeof检测数据类型,分别返回对应的数据类型小写字符。
另:用typeof检测构造函数创建的Number,String,Boolean都返回object
基本数据类型中:null 。引用数据类型中的:Array,Object,Date,RegExp。不可以用typeof检测。都会返回小写的object
2 . instanceof
除了使用typeof来判断,还可以使用instanceof。instanceof运算符需要指定一个构造函数,或者说指定一个特定的类型,它用来判断这个构造函数的原型是否在给定对象的原型链上。
基本数据类型中:Number,String,Boolean。字面量值不可以用instanceof检测,但是构造函数创建的值可以
3 .constructor
constructor是prototype对象上的属性,指向构造函数。根据实例对象寻找属性的顺序,若实例对象上没有实例属性或方法时,就去原型链上寻找,因此,实例对象也是能使用constructor属性的。
4 . 使用Object.prototype.toString.call()检测对象类型
可以通过toString() 来获取每个对象的类型。为了每个对象都能通过 Object.prototype.toString() 来检测,需要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调用,传递要检查的对象作为第一个参数,称为thisArg。
使用Object.prototype.toString.call()的方式来判断一个变量的类型是最准确的方法。
4、深拷贝
const obj1 = {
age: 20,
name: ‘xxx’,
address: {
city: ‘beijing’
},
arr: [‘a’, ‘b’, ‘c’]
}
const obj2 = deepClone(obj1)
obj2.address.city = ‘shanghai’
obj2.arr[0] = ‘a1’
console.log(obj1.address.city)
console.log(obj1.arr[0])
function deepClone(obj = {}) {
if (typeof obj !== ‘object’ || obj == null) {
// obj 是 null ,或者不是对象和数组,直接返回
return obj
}
// 初始化返回结果
let result
if (obj instanceof Array) {
result = []
} else {
result = {}
}
for (let key in obj) {
// 保证 key 不是原型的属性
if (obj.hasOwnProperty(key)) {
// 递归调用!!!
result[key] = deepClone(obj[key])
}
}
// 返回结果
return result
}