原创:前端二牛
![56c8c7a20bb7d7ea62a1075965f2f724.png](https://img-blog.csdnimg.cn/img_convert/56c8c7a20bb7d7ea62a1075965f2f724.png)
在JavaScript中,如果要复制一个变量我们应该怎么做呢?下面这种做法是最简单的一种形式:
- //把a复制给b
- let a
- =
- 12
- ;
- let b
- =
- a
- ;
这种复制方法只能适用于基本类型,如果 a是对象怎么办呢?我们先来看看上面的代码在内存中做了什么事:
![36096e545a22d037847ea27c5d9ee1b1.png](https://img-blog.csdnimg.cn/img_convert/36096e545a22d037847ea27c5d9ee1b1.png)
声明了变量 a=12,栈内存会分配一块区域来存储,如上图所示。把 a赋给 b,会在栈中重新开辟一块区域来存储 b,并且 b的值就是 a的值。
假如 a是对象,内存做了什么事呢?来看下面的例子:
- let
- a
- =
- {};
- let
- b
- =
- a
- ;
![cbcd0c1a13f5838fa204eb9a571eb579.png](https://img-blog.csdnimg.cn/img_convert/cbcd0c1a13f5838fa204eb9a571eb579.png)
如图所示,对象是存储在堆内存中的,栈中保存的是地址值,使用这种方式复制对象只不过是复制了该对象的引用而已,对象实体还是只有一个。那么对象应该怎样复制呢?对象的复制其实也就是产生一个一模一样的对象,对象包含属性和方法,我们创建一个新对象,将旧对象的属性和方法赋给新对象,这样不就是复制了一个对象吗?顺着这个思路,我们来看下面的代码:
- function
- copy
- (
- obj
- ){
- //基本类型和函数直接返回
- if
- (!(
- obj
- instanceof
- Object
- )
- ||
- typeof
- obj
- ===
- 'function'
- )
- return
- obj
- ;
- let newObj
- =
- {};
- if
- (
- obj
- instanceof
- Array
- )
- newObj
- =
- [];
- for
- (
- let p in obj
- ){
- newObj
- [
- p
- ]
- =
- obj
- [
- p
- ];
- }
- return
- newObj
- ;
- }
- let p
- =
- {
- name
- :
- 'bob'
- ,
- friends
- :
- [
- 'jack'
- ,
- 'rose'
- ]
- }
- let p2
- =
- copy
- (
- p
- );
- console
- .
- log
- (
- p2
- );
定义一个 copy函数,接收一个参数,用以实现对象的复制,如果参数是基本类型或函数就直接返回。函数体内声明一个新对象 newObj,然后遍历参数 obj,将其每一个属性都赋给 newObj,最后返回 newObj。接着使用 copy方法生成了 p的一个复制对象 p2,结果如下图所示:
![dad4efd33dcc400848ea0dfe2d1cf17d.png](https://img-blog.csdnimg.cn/img_convert/dad4efd33dcc400848ea0dfe2d1cf17d.png)
但是这样有一个问题,我们来看下面的代码:
- p2
- .
- friends
- .
- push
- (
- 'lily'
- );
- console
- .
- log
- (
- p2
- .
- friends
- );
- //["jack