值传递:基本数据类型传递数据(数据发生改变的时候,另一个数据不会发生改变)
引用传递:引用数据类型传递数据,复制另一个引用数据类型的地址,所以当数据发生改变的时候,另一个引用数据类型的数据也会发生改变。因为他们的两个只想同一地址。
1.浅拷贝:当一个对象复制另一个对象的数据后,当改变其中一个对象的数据后,另一个对象的数据也会发生改变,这就是浅拷贝;
2.深拷贝:当一个对象复制另一个对象的数据后,当改变其中一个对象的数据后,另一个对象的数据不会发生改变,这就是深拷贝;
(1).最简单的浅拷贝
var
obj = {
a:
1,
b:
2,
c:
3 };
var
newObj =
obj;
newObj.
a =
10;
console.
log(
obj);
//{a:10,b:2,c:3}
console.
log(
newObj);
//{a:10,b:2,c:3};
(2).ES6对象的方法:Object.assign():第一个参数是目标对象,后面的参数都是源对象(需要拷贝的对象);返回值是合并后的对象。
例:当对象是多层的时候
var
obj = {
data: {
a:
1,
b:
2,
c:
3 } };
var
newObj =
Object.
assign({},
obj);
newObj.
data.
a =
10;
console.
log(
obj,
newObj)
3、自己封装copy的方法
var
obj = {
"data"
: {
'a'
:
'1' },
"b"
:
"1",
"c"
:
"2"
}
function
copy(
obj) {
var
newObj = {};
for (
var
key
in
obj) {
newObj[
key] =
obj[
key];
}
return
newObj;
}
var
newObj =
copy(
obj);
console.
log(
newObj)
//{"data":{'a':'1'},"b":"1","c":"2"}
newObj.
data.
a =
10;
//二层对象进行的是浅拷贝
newObj.
b =
50;
//一层对象进行生拷贝
console.
log(
obj,
newObj)
//{"data":{'a':'10'},"b":"1","c":"2"},{"data":{'a':'10'},"b":"50","c":"2"}
4、$.extend({},{})
var
obj = {
data: {
a:
1,
b:
2,
c:
3 } };
var
newObj =
$.
extend({},
obj);
newObj.
data.
a =
10;
console.
log(
obj,
newObj)
深拷贝
1、Object.assign()
前提是对象只有一层
var
obj = {
a:
1,
b:
2,
c:
3 };
var
newObj =
Object.
assign({},
obj);
newObj.
a =
20;
console.
log(
obj,
newObj)
2、$.extend()
当第一个参数是true的时候是深拷贝
当不传递的时候是浅拷贝
var
obj = {
data: {
a:
1,
b:
2,
c:
3 } };
var
newObj =
$.
extend(
true, {},
obj);
newObj.
data.
a =
20;
console.
log(
obj);
console.
log(
newObj)
3、JSON.stringify;但目标对象有要求(非 undefined,function)
var
obj = {
data: {
a:
1,
b:
2,
c:
3 } };
var
newObj =
JSON.
parse(
JSON.
stringify(
obj));
newObj.
data.
a =
20;
console.
log(
obj);
console.
log(
newObj)
缺点是函数不能被赋值
4.递归方法
4.递归方法
function
deepClone(
initalObj,
finalObj) {
var
obj =
finalObj || {};
for (
var
i
in
initalObj) {
if (
typeof
initalObj[
i] ===
'object') {
obj[
i] = (
initalObj[
i].
constructor ===
Array) ? [] : {};
arguments.
callee(
initalObj[
i],
obj[
i]);
}
else {
obj[
i] =
initalObj[
i];
}
}
return
obj;
}
上述代码确实可以实现深拷贝。但是当遇到两个互相引用的对象,会出现死循环的情况。为了避免相互引用的对象导致死循环的情况,则应该在遍历的时候判断是否相互引用对象,如果是则退出循环。
改进版代码如下:
function
deepClone(
initalObj,
finalObj) {
var
obj =
finalObj || {};
for (
var
i
in
initalObj) {
var
prop =
initalObj[
i];
// 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
if (
prop ===
obj) {
continue;
}
if (
typeof
prop ===
'object') {
obj[
i] = (
prop.
constructor ===
Array) ? [] : {};
arguments.
callee(
prop,
obj[
i]);
}
else {
obj[
i] =
prop;
}
}
return
obj;
}
使用的时候这样写:
var Doctor = deepCopy(Chinese);
现在,给父对象加一个属性,值为数组。然后,在子对象上修改这个属性:
Chinese.birthPlaces = ['北京','上海','香港'];
Doctor.birthPlaces.push('厦门');
这时,父对象就不会受到影响了。
alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门
alert(Chinese.birthPlaces); //北京, 上海, 香港
目前,jQuery库使用的就是这种继承方法。
5.使用Object.create()方法;直接使用var newObj = Object.create(oldObj),可以达到深拷贝的效果。
function
deepClone(
initalObj,
finalObj) {
var
obj =
finalObj || {};
for (
var
i
in
initalObj) {
var
prop =
initalObj[
i];
// 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
if (
prop ===
obj) {
continue;
}
if (
typeof
prop ===
'object') {
obj[
i] = (
prop.
constructor ===
Array) ? [] :
Object.
create(
prop);
}
else {
obj[
i] =
prop;
}
}
return
obj;
}