赋值和拷贝

一、问题描述

// 示例

import React from "react";
import ReactDOM from "react-dom";
import _ from "lodash";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      arr: []
    };
  }
  render() {
    let { arr } = this.state;
    return <div>arr: {arr.join()}</div>;
  }
  componentDidMount() {
    let arr = _.cloneDeep(this.state.arr);
    arr.push(1);
    this.setState({
      arr: arr
    });
  }
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

第1段代码,arr和this.state.arr,值不同,arr变了,在setState前,this.state.arr没变。

第2段代码,arr和this.state.arr,值相同,arr变了,在setState前,this.state.arr也变了,但是setState必须要写。

// 第1段代码,深拷贝

this.state = {
      arr: []
    };

let arr = _.cloneDeep(this.state.arr);
    arr.push(1);
    this.setState({
      arr: arr
    });
// 第2段代码,引用类型的赋值
this.state = {
      arr: []
    };

let arr = this.state.arr;
        arr.push(1);
        this.setState({
            arr: this.state.arr
        });

二、问题分析

1、赋值

A、基本数据类型传值

基本数据类型的赋值(=)是在内存中新开辟一段栈内存,然后再把再将值赋值到新的栈中。

var a = 10;
var b = a;

a++ ;
console.log(a); // 11
console.log(b); // 10

B、引用数据类型传址

引用类型的赋值是传址,只是改变指针的指向。

var a = {}; // a保存了一个空对象的实例
var b = a;  // a和b都指向了这个空对象

a.name = 'camille';
console.log(a.name); // 'camille'
console.log(b.name); // 'camille'

b.age = 28;
console.log(b.age);// 28
console.log(a.age);// 28

console.log(a == b);// true

2、浅拷贝,将A对象拷贝到B对象中,但不包括A里面的子对象。

3、深拷贝,将A对象拷贝到B对象中,包括A里面的子对象。

    // 内部方法:用户合并一个或多个对象到第一个对象
    // 参数:
    // target 目标对象  对象都合并到target里
    // source 合并对象
    // deep 是否执行深度合并
    function extend(target, source, deep) {
        for (key in source)
            if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
                // source[key] 是对象,而 target[key] 不是对象, 则 target[key] = {} 初始化一下,否则递归会出错的
                if (isPlainObject(source[key]) && !isPlainObject(target[key]))
                    target[key] = {}

                // source[key] 是数组,而 target[key] 不是数组,则 target[key] = [] 初始化一下,否则递归会出错的
                if (isArray(source[key]) && !isArray(target[key]))
                    target[key] = []
                // 执行递归
                extend(target[key], source[key], deep)
            }
            // 不满足以上条件,说明 source[key] 是一般的值类型,直接赋值给 target 就是了
            else if (source[key] !== undefined) target[key] = source[key]
    }

    // Copy all but undefined properties from one or more
    // objects to the `target` object.

$.extend = function(target){
        var deep, args = slice.call(arguments, 1);

        //第一个参数为boolean值时,表示是否深度合并
        if (typeof target == 'boolean') {
            deep = target;
            //target取第二个参数
            target = args.shift()
        }
        // 遍历后面的参数,都合并到target上
        args.forEach(function(arg){ extend(target, arg, deep) })
        return target
  }

三、归纳总结

旧数据a和新数据b
操作类型a是基本类型

a是引用类型

赋值

适用于拷贝基本数据类型数据

改变a,b不变;改变b,a不变;

(互不影响)

1、单个修改,ab互相影响,cd互相影响

改变a的属性,b会变;改变b的属性,a会变;

//对象,ab都会变成tom

var a = {'name': 'lily'};

var b = a;

a.name = 'marry';

b.name = 'tom';

 

//数组, cd都会变成[1, 2]

var c = [];

var d = c;

c.push(1);

d.push(2);

赋值,改变对象指针,仍引用同一对象。 

2、整体赋值,ab互不影响,cd互不影响

var a = {'name': 'lily'};

var b = a;

a = {'name': 'marry'};

b = {'name': 'tom'};

 

var c = [];

var d = c;

c = [1, 3, 5];

d = [2, 4, 6];

浅拷贝

只复制一层对象的属性,并不包括对象里面的为引用类型的数据

适用于拷贝单层引用类型数据。

 

改变a,b不变;改变b,a不变;

(互不影响)

1、单个修改,表层,ab互不影响;深层,ab互相影响

改变a的二层属性,b会变;改变b的二层属性,a会变;

//对象

var a = {
  'name' : 'zhangsan',
  'age' : '18',
  'language' : [1, [2,3], [4,5]],
};
var b = _.clone(a);
a.language[2] = 34;
b.age = "20";
b.language[2] = ["四","五"];

浅拷贝,创建了新对象。

 

2、整体赋值,ab互不影响,cd互不影响

var a = {'name': 'lily'};

var b = _.clone(a);

a = {'name': 'marry'};

b = {'name': 'tom'};

 

var c = [];

var d = _.clone(c);

c = [1, 3, 5];

d = [2, 4, 6];

 

深拷贝

适用于拷贝深层引用类型的数据。

改变a,b不变;改变b,a不变;

(互不影响)

 

1、单个修改,ab互不影响

改变a的属性,b不会变;改变b的属性,a不会变;

//对象

var a = {
  'name' : 'zhangsan',
  'age' : '18',
  'language' : [1, [2,3], [4,5]],
};
var b = _.cloneDeep(a);
a.language[2] = 34;
b.age = "20";
b.language[2] = ["四","五"];

 

2、整体赋值,ab互不影响,cd互不影响

var a = {'name': 'lily'};

var b = _.cloneDeep(a);

a = {'name': 'marry'};

b = {'name': 'tom'};

 

var c = [];

var d = _.cloneDeep(c);

c = [1, 3, 5];

d = [2, 4, 6];

 

转载于:https://www.cnblogs.com/camille666/p/js_fuzhi_copy.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值