数据分为基本数据类型(String, Number, Boolean, Null, Undefined,Symbol)和对象数据类型。
基本数据类型的特点:直接存储在栈(stack)中的数据
引用数据类型的特点:存储的是该对象在栈中引用,真实的数据存放在堆内存里
引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。
深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
实现浅拷贝
// 实现方式一:Object.assign
let target = {};
let source = {
a: '123',
b: { name: 'yd' }
};
Object.assign(target, source);
console.log(target); // { a: '123', b: { name: 'yd' } }
// 实现方式二:Array.prototype.slice、Array.prototype.concat
let array = [{ a: 1 }, { b: 2 }];
console.log(array.slice(0)); // [{a: 1}, {b: 2}]
console.log([].concat(array)); // [{a: 1}, {b: 2}]
// 实现方式三:扩展运算符
let obj = {
a: 1,
b: { c: 1 }
};
console.log({ ...obj }); // { a: 1, b: { c: 1 } }
// 实现方式四:
function cloneShallow(source) {
let target = {};
for (let key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
return target;
}
实现深拷贝
// 实现方式一:JSON.stringify
/*
* 缺点:
* 1、日期类型的数据会直接变成字符串的形式,而不是对象的形式
* 2、正则类型的数据会变成空对象{}
* 3、函数会丢失
*/
// 实现方式二:自定义实现深拷贝函数
function cloneDeep(data) {
// 当 null NaN undefined number string 等基本数据类型时直接返回
if (data === null || typeof data !== 'object') {
return data
}
// Date类型
if (data instanceof Date) {
return new Date(data.valueOf())
}
// 正则类型
if (data instanceof RegExp) {
return new RegExp(data)
}
// Map 集合
if (data instanceof Map) {
let m = new Map()
data.forEach((v, k) => m.set(k, cloneDeep(v)))
return m
}
// Set 集合
if (data instanceof Set) {
let s = new Set()
for (let val of data.values()) {
s.add(cloneDeep(val))
}
return s
}
// 数组、对象等引用数据类型
if (typeof data === 'object') {
const copyData = Array.isArray(data) ? [] : {}
for (const key in data) {
if (data.hasOwnProperty(key)) {
copyData[key] = cloneDeep(data[key])
}
}
return copyData
}
// 函数
if (data instanceof Function) {
return (new data()).constructor
}
return data
}
// 实现方式三:使用 lodash.js 中的 cloneDeep 函数
实现 JSON(parse + stringify)
if (!window.JSON) {
window.JSON = {
parse: function (sJSON) {
return eval('(' + jsonStr + ')');
// return new Function('return ' + jsonStr)();
},
stringify: (function () {
var toString = Object.prototype.toString;
var isArray = Array.isArray || function (array) {
return toString.call(array) === '[object Array]'
};
var escMap = {
'"': '\\"',
"\\": "\\\\",
"\b": "\\b",
"\f": "\\f",
"\n": "\\n",
"\r": "\\r",
"\t": "\\t",
};
var escFunc = function (m) {
return escMap[m] || "\\u" + (m.charCodeAt(0) + 0x10000).toString(16).substr(1);
};
var escRE = /[\\"\u0000-\u001F\u2028\u2029]/g;
return function stringify(value) {
if (value == null) {
return 'null';
} else if (typeof value === 'number') {
// isFinite() 函数用于检查其参数是否是无穷大,如果参数是 NaN,正无穷大或者负无穷大,会返回 false,其他返回 true。
return isFinite(value) ? value.toString() : 'null';
} else if (typeof value === 'boolean') {
return value.toString();
} else if (typeof value === 'object') {
if (typeof value.toJSON === 'function') {
return stringify(value.toJSON());
} else if (isArray(value)) {
var res = '[';
for (var i = 0; i < value.length; i++) {
res += (i ? ', ' : '') + stringify(value[i]);
}
return res + ']';
} else if (toString.call(value) === '[object Object]') {
var tmp = [];
for (var k in value) {
if (value.hasOwnProperty(k)) {
tmp.push(stringify(k) + ': ' + stringify(value[k]));
}
}
return '{' + tmp.join(', ') + '}';
}
}
return '"' + value.toString().replace(escRE, escFunc) + '"';
};
})(),
};
}
网友评论