var a = 1;
console.log(a++ * (++a + a++));
解析:
a++和++a的区别:
a=1; a++ = 1; a=2; ++a = 3; a=3; a++ = 3;
a++ * (++a + a++)
= 1 * ( 3+3 ) = 6
答案:6
Number
、String
、Boolean
、undefined
、object
、Null
Symbol
。这种类型的对象永不相等,即始创建的时候传入相同的值,可以解决属性名冲突的问题,做为标记。 bigInt
。是指安全存储、操作大整数。目前JS的数据类型共有8种,按照类型来分,可分为基本数据类型和引用数据类型:
基本数据类型:Number
、String
、Boolean
、undefined
、Null
、Symbol
、bigInt
;
引用数据类型:Object
(Object是个大类,包含Array数组、function函数、Date日期等)
基本数据类型与引用数据类型区别
1. 声明变量时内存分配不同
栈
当中,也就是变量访问的位置堆
当中,变量访问的其实是一个指针,它指向存储对象的内存地址2. 因为内存分配不同,在复制变量时结果也不一样
基本数据类型复制后,2个变量是独立的互不影响,因为是把值拷贝了一份
引用数据类型则是复制了一个指针,2个变量指向的值是该指针所指向的内容,一旦一方修改,另一方也会受到影响
这里实际上涉及了JS的深拷贝和浅拷贝
3. 参数传递不同
1.基本数据类型
// 基本数据类型
// 赋值(不是深拷贝也不是浅拷贝)(非要说就是深拷贝)(互不影响)
let a = 5;
let b = a;
b = 3;
console.log(a,b);// 5,3
2.引用数据类型
// 数组与对象的赋值
// 浅拷贝 (藕断丝连)
let arr = [1,2,3];
let newarr = arr;
newarr.push(4);
console.log(arr); // [1,2,3,4]
console.log(newarr); // [1,2,3,4]
// 解构赋值
// 针对一维数组和对象可以看作是深拷贝,多维就是浅拷贝
let arr = [1,2,3];
let newarr = [...arr];
newarr.push(4);
console.log(arr); // [1,2,3]
console.log(newarr); // [1,2,3,4]
let arr2 = [[1,2,3],[4,5,6]];
let newarr2= [...arr2];
newarr2.push(888)
console.log(arr2); // [[1,2,3],[4,5,6],888]
console.log(newarr2); // [[1,2,3],[4,5,6],888]
总结:
练习题:下面代码输出结果是什么?
var a = {
n: 0,
}
var b = a;
a.n = a = {n:1};
console.log(b.n);
// 深拷贝的用法
let list = [
{id:1,name:'aaa',sex:'01'},
{id:2,name:'bbb',sex:'02'},
{id:3,name:'ccc',sex:'01'},
]
// let newlist = list; // 对象赋值是浅拷贝
let newlist = JSON.parse(JSON.stringify(list)); // 利用JSON.parse(JSON.stringify())转化为深拷贝
newlist.push({id:44});
console.log(list === newlist); // false
该方法是用JSON.stringify将对象序列化为字符串,然后在用JSON.parse将json字符串解析为对象,解析的时候会自己去构建新的内存地址存放新对象。
缺点:
// 标准的数据类型 =>引用数据类型(数组和对象)
function deepCopy(obj) {
// 创建一个新对象
let result = {}
let keys = Object.keys(obj),
key = null,
temp = null;
for (let i = 0; i < keys.length; i++) {
key = keys[i];
temp = obj[key];
// 如果字段的值也是一个对象则递归操作
if (temp && typeof temp === 'object') {
result[key] = deepCopy(temp);
} else {
// 否则直接赋值给新对象
result[key] = temp;
}
}
return result;
}
let obj={
str:'name',
num:123,
arr:[1,2,3,4],
obj:{id:1,student:'小米'}
}
let newobj=deepClone(obj);
newobj.str="新值";
console.log(obj === newobj); // false
lodash的_.cloneDeep()支持循环对象、大量的内置类型,对很多细节都处理的比较不错,推荐使用。
var _ = require('lodash');
var obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);// false
会发现lodash是用一个栈记录了所有被拷贝的引用值,如果再次碰到同样的引用值的时候,不会再去拷贝一遍,而是利用之前已经拷贝好的。
综上,在生产环境,我们推荐使用lodash的cloneDeep()。
未完待续,持续更新中,点赞收藏加关注,方便下次回顾哦~