传值与传址

了解了基本数据类型与引用类型的区别之后,我们就应该能明白传值与传址的区别了。
在我们进行赋值操作的时候,基本数据类型的赋值(=)是在内存中新开辟一段栈内存,然后再把再将值赋值到新的栈中。例如:

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

所以说,基本类型的赋值的两个变量是两个独立相互不影响的变量。

但是引用类型的赋值是传址。只是改变指针的指向,例如,也就是说引用类型的赋值是对象保存在栈中的地址的赋值,这样的话两个变量就指向同一个对象,因此两者之间操作互相有影响。例如:

var a = {}; // a保存了一个空对象的实例 var b = a; // a和b都指向了这个空对象 a.name = 'jozo'; console.log(a.name); // 'jozo' console.log(b.name); // 'jozo' b.age = 22; console.log(b.age);// 22 console.log(a.age);// 22 console.log(a == b);// true

浅拷贝

先来看一段代码的执行:

var obj = {a: 1, b: {c: 2}} var obj1 = obj var obj2 = shallowCopy(obj); function shallowCopy(src) { var dst = {}; for (var prop in src) { if (src.hasOwnProperty(prop)) { dst[prop] = src[prop]; } } return dst; } var obj3 = Object.assign({}, obj) obj.a = 2 obj.b.c = 3 console.log(obj) // {a: 2, b: {c: 3}} console.log(obj1) // {a: 2, b: {c: 3}} console.log(obj2) // {a: 1, b: {c: 3}} console.log(obj3) // {a: 1, b: {c: 3}}

这段代码可以说明赋值得到的对象 obj1 只是将指针改变,其引用的仍然是同一个对象,而浅拷贝得到的的 obj2 则是重新创建了新对象。但是,如果原对象obj中存在另一个对象,则不会对对象做另一次拷贝,而是只复制其变量对象的地址。这是因为浅拷贝只复制一层对象的属性,并不包括对象里面的为引用类型的数据。
对于数组,更长见的浅拷贝方法便是slice(0)和 concat()
ES6 比较常见的浅拷贝方法便是 Object.assign

深拷贝

通过上面的这些说明,相信你对深拷贝大致了解了是怎样一个东西了:深拷贝是对对象以及对象的所有子对象进行拷贝。那么如何实现这样一个深拷贝呢?

1. JSON.parse(JSON.stringify(obj))

对于常规的对象,我们可以通过JSON.stringify来讲对象转成一个字符串,然后在用JSON.parse来为其分配另一个存储地址,这样可以解决内存地址指向同一个的问题:

var obj = {a: {b: 1}} var copy = JSON.parse(JSON.stringify(obj)) obj.a.b = 2 console.log(obj) // {a: {b: 2}} console.log(copy) // {a: {b: 1}}

但是 JSON.parse()JSON.stringify也存在一个问题,JSON.parse()和J SON.stringify()能正确处理的对象只有Number、String、Array等能够被 json 表示的数据结构,因此函数这种不能被 json 表示的类型将不能被正确处理。

var target = {a: 1, b: 2, hello: function() { console.log("Hello, world!"); } }; var copy = JSON.parse(JSON.stringify(target)); console.log(copy); // {a: 1, b: 2} console.log(JSON.stringify(target)); // "{"a":1,"b":2}"

2. 遍历实现属性复制

既然浅拷贝只能实现非object第一层属性的复制,那么遇到object只需要通过递归实现浅拷贝其中内部的属性即可:

function extend (source) { var target if (typeof source === 'object') { target = Array.isArray(source) ? [] : {} for (var key in source) { if (source.hasOwnProperty(key)) { if (typeof source[key] !== 'object') { target[key] = source[key] } else { target[key] = extend(source[key]) } } } } else { target = source } return target } var obj1 = {a: {b: 1}} var cpObj1 = extend(obj1) obj1.a.b = 2 console.log(cpObj1) // {a: {b: 1}} var obj2 = [[1]] var cpObj2 = extend(obj2) obj2[0][0] = 2 console.log(cpObj2) // [[1]]

我们再来看一下 Zepto 中深拷贝的代码:

    // 内部方法:用户合并一个或多个对象到第一个对象// 参数:// 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] }

内部实现其实也是差不多。

js 浅拷贝和深拷贝相关推荐

  1. js - 浅拷贝和深拷贝

    在项目中,经常会用到拷贝. 浅拷贝和深拷贝,相信大家都知道区别,但是怎么去实现呢? 我会分享一些项目中经常会用到的一些方法,然后再手写一个深/浅拷贝的方法. 1. Object.assign 相信这个 ...

  2. 关于js浅拷贝与深拷贝的理解

    前端开发中,一般情况下,很少会去在意深拷贝与浅拷贝的关系. 大家知道,js变量有2种数据类型:基本类型和引用类型.基本类型的拷贝是将整个值完全拷贝一份的,也就是深拷贝.就是开辟了新的堆内存.所以基本类 ...

  3. JS: 浅拷贝vs深拷贝 | 刷题打卡

    1. 概念 在JavaScript中,拷贝一般是指变量的复制过程. 对于简单类型,拷贝就是直接赋值的过程: 对于复杂类型,浅拷贝是指复制对象的引用地址的过程.如果修改了源对象的某个属性,由于引用相同, ...

  4. js之浅拷贝和深拷贝

    js数据类型主要分基本数据类型和引用数据类型.前者包括Number,String等,后者主要是Object,因此以下会针对不同的数据类型来分析,需要的朋友可以参考一下 1.js内存 js内存,或者说大 ...

  5. 说说JS中的浅拷贝与深拷贝

    outline: 为什么要说JS中深拷贝与浅拷贝 JS对类型的分类 immutable与mutable 简单类型检测 浅拷贝VS深拷贝 为什么要说JS中深拷贝与浅拷贝 近来在研读underscore的 ...

  6. js 浅拷贝直接赋值_js 深拷贝 vs 浅拷贝

    本文主要讲一下 js 的基本数据类型以及一些堆和栈的知识和什么是深拷贝.什么是浅拷贝.深拷贝与浅拷贝的区别,以及怎么进行深拷贝和怎么进行浅拷贝. 本文思维导图如下:本文思维导图 堆和栈的区别 其实深拷 ...

  7. js 浅拷贝直接赋值_JS中实现浅拷贝和深拷贝的代码详解

    (一)JS中基本类型和引用类型 JavaScript的变量中包含两种类型的值:基本类型值 和 引用类型值,在内存中的表现形式在于:前者是存储在栈中的一些简单的数据段,后者则是保存在堆内存中的一个对象. ...

  8. js 浅拷贝直接赋值_浅析JavaScript解析赋值、浅拷贝和深拷贝的区别

    一.赋值(Copy) 赋值是将某一数值或对象赋给某个变量的过程,分为: 1.基本数据类型:赋值,赋值之后两个变量互不影响 2.引用数据类型:赋**址**,两个变量具有相同的引用,指向同一个对象,相互之 ...

  9. js 浅拷贝直接赋值_JS中的赋值、浅拷贝与深拷贝

    作者:奚杰 拷贝是写代码中经常使用的方法.浅拷贝与深拷贝是指拷贝的两种情况.本文将深入探究JS的赋值.浅拷贝与深拷贝. 数据类型 在探究深拷贝与浅拷贝之前,我们先梳理一下JS的数据类型.在JavaSc ...

  10. 理清JS中的深拷贝与浅拷贝

    作者:Manjula Dube译者:前端小智来源:Medium 为了保证的可读性,本文采用意译而非直译. 浅拷贝是对象的逐位复制.创建一个新对象,该对象具有原始对象中值的精确副本.如果对象的任何字段是 ...

最新文章

  1. const引用和非const引用
  2. [JQuery]用InsertAfter实现图片走马灯展示效果
  3. 【Linux】一步一步学Linux——pmap命令(145)
  4. 10年老电脑如何提速_告别求人!3个方法教你怎样让你的电脑快的嗖嗖的!
  5. 电脑手写输入法_QQ拼音输入法除了能打字,竟然还有 N 多妙用!
  6. keras如何保存模型
  7. 【人民币识别】基于matlab GUI形态学钞票面额识别与统计【含Matlab源码 906期】
  8. 图像复原matlab论文,基于matlab图像复原论文
  9. 通达信l2高级行情服务器地址配置文件,疯赢版通达信更好用——开通level2行情,添加龙虎榜数据...
  10. 贴吧一键签到机selenium自动化
  11. 小程序tab栏菜单的切换
  12. 校园网如何使用IPv6
  13. 关于计算机的英语作文初中,computer初中英语作文范文
  14. 百度2017春招笔试真题编程题集合 [编程题]买帽子
  15. 开源软电话 (Open Source Soft Phones)
  16. 18118 勇者斗恶龙(c++ STL sort的运用)
  17. 风险管理_cissp
  18. c语言规定 标识符由,【填空题】C语言的标识符命名规则规定标识符可以由字母数字和下划线组成,首字符不能是 。 (4.0分)...
  19. 北语期末考试计算机组成原理,基础知识一认识计算机网络_1课件
  20. 用Python软件绘制五角星

热门文章

  1. 帮Python找“对象”
  2. 千万不要错过云计算兴起的时代
  3. 别怕,“卷积“其实很简单
  4. 初识数据库——Mysql入门
  5. 降维--PCA学习笔记
  6. hbase中为何不能向表中插入数据_Python自带的数据库,用起来真方便!
  7. hive 列表去重_Hive企业级调优
  8. 力扣-204 计数质数
  9. 力扣-58 最后一个单词的长度
  10. virtualenvwrapper安装及使用