JS中的两种数据类型以及实现引用类型的深拷贝
一.前言
我们知道,在JS中数据类型按照访问方式和存储方式的不同可分为基本类型和引用类型。
基本类型
基本类型有String、Boolean、Number,Undefined、Null,这些基本类型都是按值传递的,也称为值类型。
引用类型
引用类型有对象、数组、函数,它们都是按引用访问的。
二.存储方式区别
基本类型和引用类型由于两者在内存中存储的方式不同,造成两者访问的方式也不同。其中,基本类型存储在内存的栈中,是按值访问;引用类型存储在内存的堆中,是按引用访问。可如下图所示:
当有
var n1 = 10;
var n2 = 10; var arr1 = [1,2,3,4]
var arr2 = [1,2,3,4]
其在内存中存储方式如图:
值类型是在栈中直接保存的变量的实际值,而引用类型在栈中仅仅保存的是变量指向堆中的地址,从上图中可以看出,值类型的变量n1和n2都是10,但是在栈中却为这两个变量分别开辟了两块空间来存储,而引用类型的变量arr1和arr2也相同,但是在堆中仅仅开辟了一块内存来存储,而在栈中存储的是这两个变量指向堆中的地址,这两个变量都指向堆中的同一片地址。
三.拷贝区别
正是由于两者在存储方式上的不同,造成了两者在拷贝时的差异。首先,先看两段代码:
var n1 = 10;
//将n1拷贝给n2
var n2 = n1; n1 = 12;
console.log(n1);
console.log(n2);
先定义变量n1=10,然后将n1拷贝给n2,再接着改变n1的值为12,分别打印n1和n2的值,打印结果为:
从结果中我们可以看到,n1变为12了,但是n2不受影响,依旧是10。
再看另外一段代码:
var arr1 = [1,2,3,4]
//将arr1拷贝给arr2
var arr2 = arr1;
//向arr1中尾部添加一个元素5
arr1.push(5); console.log(arr1);
console.log(arr2);
先定义数组arr1,然后将arr1拷贝给arr2,再接着向arr1中尾部追加一个元素,分别打印arr1和arr2的值,打印结果为:
从结果中我们可以看到:我们先将arr1拷贝给了arr2,但是当我们改变arr1时,arr2也跟着一起改变了。这印证了前文所说的,arr1和arr2实际上是指向了内存中的同一片地址,当arr1发生变化时,实际上是将指向的这片内存地址中的数据变化了,而arr2也指向的是这片地址,所以arr2也会跟着变化。
上面代码中的arr2=arr1,就是我们俗称的浅拷贝,浅拷贝仅仅拷贝的是变量名,其在内存的存储没有被拷贝,指向的还是同一片内存地址,这就是造成了一个变化另外一个也跟着变化,这在日常开发中不是我们想要的。
那如何实现真正的拷贝呢?
四.实现深拷贝
真正的拷贝,就是拷贝过后,arr1和arr2指向的不再是同一片内存地址,而是分别指向各自的地址,这样发生变化的时候就不会出现同时变化,这就是深拷贝。
下面我们封装一个深拷贝函数,来实现引用类型的深拷贝:
//参数p为原对象
//参数c为原对象的类型,若原对象为数组,则传入c为[],若原对象是对象传入c为{},也可不传默认为{}
function deepCopy(p,c){
var c = c || {};
for(var i in p){
if(typeof p[i] === "object"){
c[i] = (p[i].constructor === Array)?[]:{};
deepCopy(p[i],c[i])
}else{
c[i] = p[i]
11 }
}
return c;
}
五.测试
//参数p为原对象
//参数c为原对象的类型,若原对象为数组,则传入c为[],若原对象是对象传入c为{},也可不传默认为{}
function deepCopy(p,c){
var c = c || {};
for(var i in p){
if(typeof p[i] === "object"){
c[i] = (p[i].constructor === Array)?[]:{};
deepCopy(p[i],c[i])
}else{
c[i] = p[i]
}
}
return c;
} //定义数组arr1
var arr1 = [1,2,3,4]
//将arr1拷贝给arr2
var arr2 = deepCopy(arr1,[]);
//向arr1中尾部添加一个元素5
arr1.push(5);
console.log('arr1:',arr1);
console.log('arr2:',arr2);
测试结果:
结果中可以看到,arr1变化没有引起arr2的变化,实现了真正的拷贝。
(完)
JS中的两种数据类型以及实现引用类型的深拷贝的更多相关文章
- 实现一个函数clone,可以对JS中的5种数据类型(Number、String、Object、Array、Boolean)进行值复制
实现一个函数clone,可以对JS中的5种数据类型(Number.String.Object.Array.Boolean)进行值复制
- JS中的两种刷新方法以及区别和适用范围
在项目中有一个人信息修改的页面,但是修改后显示的却是修改之前的内容,分析问题后发现查询语句写在了修改语句之前,有些某些需要又必须这么写,但是修改信息后先却显示之前的信息也太不科学了. 所以我就想用js ...
- JavaScript中的两种全局对象
这里总结的东西特别适合先学习c/c++, Java这类标准语言再学JS的童鞋们看,因为JS在程序执行之前就会初始化一个全局对象,这个全局对象到底是什么是跟JS程序运行环境有关的. 根据JavaScri ...
- Python中的几种数据类型
大体上把Python中的数据类型分为如下几类: Number(数字) 包括int,long,float,complex String(字符串) 例如:hello,"hello" ...
- 前端跨域问题相关知识详解(原生js和jquery两种方法实现jsonp跨域)
1.同源策略 同源策略(Same origin policy),它是由Netscape提出的一个著名的安全策略.同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正 ...
- 研究分析JS中的三种逻辑语句
JS中的三种逻辑语句:顺序.分支和循环语句. 一.顺序语句 代码规范如下:1. <script type="text/javascript"> var a = 10; ...
- 实验long raw 和 blob两种数据类型遇到dblink的表现
首先long raw从Oracle 10g开始就不再被建议使用,建议用blob代替.同理,long建议用clob代替. 本文从运维角度实验long raw 和 blob两种数据类型在遇到dblink时 ...
- 使geoJSONLayer能够加载两种数据类型的geojson数据
问题描述 在使用geoJSONLayer加载geojson数据时,官方文档只支持单一类型的geojson数据加载,当一个geojson数据中出现两种类型的数据时可以尝试一下方法进行解决 本场景为:点击 ...
- MySQL中的两种临时表
MySQL中的两种临时表 伯乐在线2016-07-06 05:16:52阅读(4556)评论(3) 声明:本文由入驻搜狐公众平台的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场.举报 ...
随机推荐
- 数据库审计 DBAudit - Yearning 最新版
数据库审计 DBAudit 2019/09/26 Chenxin 数据库审计 基本概念 数据库审计(简称DBAudit)能够实时记录网络上的数据库活动,对数据库操作进行细粒度审计的合规性管理,对数据库 ...
- 31、vue-cli3引入封装svg图标
svg图标放大不失真,png会出现失真现象. 一.方法一 1.在对应vue项目里添加插件 vue add svg-sprite 输入 Y 2.在执行 npm install svgo svgo-loa ...
- 深入理解C#多线程 -戈多编程
引用(http://www.cnblogs.com/luxiaoxun/p/3280146.html) 一.使用线程的好处 1.可以使用线程将代码同其他代码隔离,提高应用程序的可靠性. 2.可以使 ...
- MySQL 拿 WebShell
两种常规方法利用 MySQL getshell 的方法: select … into outfile general_log 一.select … into outfile 介绍 利用需要满足以下条件 ...
- moloch1.8.0简单操作手册
moloch1.8.0简单操作手册 Sessions 页面:Sessions主要通过非常简单的查询语言来构建表达式追溯数据流量,以便分析. SPIView 页面: SPIGraph页面:SPIGrap ...
- POJ 3080 Blue Jeans(串)
题目网址:http://poj.org/problem?id=3080 思路: 以第一个DNA序列s为参考序列,开始做以下的操作. 1.将一个字母s[i]作为匹配串.(i为当前遍历到的下标) 2.遍历 ...
- 近万字案例:Rancher + VMware PKS实现全球数百站点K8S集群管理
Sovereign Systems是一家成立于2007年的技术咨询公司,帮助客户将传统数据中心技术和应用程序转换为更高效的.基于云的技术平台,以更好地应对业务挑战.曾连续3年提名CRN,并且在2012 ...
- 百万年薪python之路 -- 生成器
1.生成器 #本质就是迭代器 1.1 生成器的构建方式 在python中有三种方式来创建生成器: 1.通过生成器函数 2.通过生成器推导式 3.python内置函数或者模块提供 1.2 生 ...
- ASP.NET WebApi+Vue前后端分离之允许启用跨域请求
前言: 这段时间接手了一个新需求,将一个ASP.NET MVC项目改成前后端分离项目.前端使用Vue,后端则是使用ASP.NET WebApi.在搭建完成前后端框架后,进行接口测试时发现了一个前后端分 ...
- 身为一个 CS专业的留学生,你还在为堆积如山的编程assignment而发愁吗?
每个人都渴望圆梦,当我们看见梦想在别人身上实现时,总在抱怨幸运之神为何不眷顾自己:其实更多的时候,梦想就在你身边的不远处,只要你迈出正确的步伐. 记得刚入大学时,意气风发.我以全班前几名的优异成绩考入 ...