目录
一:数据类型
-
数据类型
基本数据类型:null,string,undefined,number,Boolean,symbol
引用数据类型:object对象、Array数组、Function函数。
-
两种数据类型的区别
栈(stack):是自动分配的内存空间,大小固定,内存由系统自动释放。
堆(heap):是动态分配的内存,大小不一定,会自动释放
-
存储位置不同: 基本类型存储在栈中,大小固定,占空间小,是频繁操作的数据。 引用数据类型存储在堆中,占据空间大,大小不固定。
-
传值方式不同: 基本数据类型 按值传递,无法改变一个基本数据类型的值
引用数据类型 应用类型值可以改变
-
值 基本类型的值是不可变的:即任何方法都无法改变一个基本类型的值,我们不能给基本类型添加属性和方法; 引用类型的值是可变的:我们可为为引用类型添加属性和方法,也可以删除其属性和方法。
-
比较
-
基本数据类型的比较是值的比较,只有在它们的值相等的时候它们才相等;
-
引用数据类型的比较是引用的比较,因为它是按引用访问的,换句话说就是比较两个对象的堆内存中的地址是否相同。
-
-
js存储有 基础类型是栈存储,引用数据类型是堆存储。
//直接赋值
const initDate = [1 ,{obj:'123'}];
const finalDate = initDate;
finalDate[0] = 2;
finalDate[1] = '456';
console.log(initDate);//[ 2, { obj: '456'}]
console.log(finalDate);//[ 2, { obj: '456' }]
// 基本数据类型
let str1 = '123';
str2 = str1;
str2 = '456';
console.log(str1);// '123'
console.log(str2);// '456'
// 引用数据类型
let arr1 = [1, 2, 3];
arr2 = arr1;
arr2.push(4);
console.log(arr1); //[1,2,3,4]
console.log(arr2); //[1,2,3,4]
例子可以看出:
直接赋值情况下,finalDate也会改变原来的initDate
基本数据类型的拷贝,拷贝的是值,修改str2不影响str1
引用数据类型的拷贝,拷贝的是地址,修改str2会修改str1
二:拷贝
赋值: 修改赋值后的数据,不管是基本数据类型还是引用数据类型,都会影响到原数据。
浅拷贝:一层拷贝,拷贝的是地址。在浅拷贝中,修改基本数据类型不会影响原有数据的基本数据类型,修改引用数据类型会影响到原有的数据类型。
深拷贝:无限层级拷贝,拷贝值。在深拷贝中,修改基本数据类型和引用数据类型都不会影响原有的数据类型。
代码实现浅拷贝
1. 循环遍历对象可枚举值
// 手写浅拷贝
const arr1 = [1, 2, ['html', 'css'], 4];
const shallowClone = (arr) => {
const dst = [];
for (let prop in arr) {
console.log(prop)
if (arr.hasOwnProperty(prop)) {
dst[prop] = arr[prop];
}
}
return dst;
}
const arr2 = shallowClone(arr1);
arr2[2].push('Javascript');
arr2[3] = 5;
console.log(arr1);
// [ 1,2,['html','css','Javascript'], 4 ]
console.log(arr2);
// [1,2,['html','css','Javascript'], 5 ]
for ... in : 遍历object对象arr1 ,将其可枚举值列举出来
hasOwnProperty(): 检查该枚举值是否属于该对象arr1,如果是继承过了的就去掉,如果是自身的则进行拷贝。
2. object.assign()
ES6新增方法,把任意多个源对象自身的可枚举对象拷贝给目标对象,然后返回目标对象
const obj = {
name : "mingming",
age : "20",
skill : {
read : "html",
write : "css"
},
like : ['yy','zz','mm']
}
const newobj = Object.assign({},obj)
newobj.name = "ss"
newobj.skill.read = "js"
newobj.like = ["ee"]
console.log(obj)
// { name: 'mingming',
// age: '20',
// skill: { read: 'js', write: 'css' },
// like: [ 'yy', 'zz', 'mm' ] }
console.log(newobj)
// { name: 'ss',
// age: '20',
// skill: { read: 'js', write: 'css' },
// like: [ 'ee' ] }
可以看出,object.assign()拷贝第一层基本数据,完全拷贝,第二次引用类型浅拷贝,拷贝地址。
3. Array.propotype.concat()
concat()是数组的内置方法,合并两个或多个数组,不会改变现有数组,返回新的数组
4. Array.propotype.slice()
concat()是数组的内置方法,该方法返回一个新的对象,不改变原数组
5. 展开运算符...obj
用const obj2 = {...obj1}方式进行拷贝
代码实现深拷贝
1. JSON.parse( JSON.stringify() )
JSON.stringify() :将对象转为JSON字符串
JSON.parse() : 将字符串解析成对象
const arr1 = [
3,
{
name:'ww'
},
];
let arr2 = JSON.parse(JSON.stringify(arr1));
arr2[0] = 2;
arr2[1].name = 'zz';
console.log(arr1);
// [ 3,name:'ww']
console.log(arr2);
// [ 2, { name: 'zz' } ]