从JS的深拷贝与浅拷贝到jq的$.extend()方法
一、堆内存与栈内存
堆和栈都是内存中划分出来的用来存储的区域,栈为自动分配的内存空间,它由系统自动释放,堆为动态分配的内存,大小不定也不会自动释放。
二、js基本数据类型与引用类型的不同
基本数据类型(boolean,undefined,null,string,number)
1.基本数据类型存放在栈内存中
是存放在栈中的简单数据段,数据大小确定,内存空间大小可以分配,是直接按值存放的,所以可以直接访问。
2、基本数据类型值不可变
js中给基本类型赋值或操作基本类型数据时,并没有改变基本类型的原始值,数字和布尔类型的值显然是不可变的,字符串虽然有很多方法去操作,但都是在创造一个新的字符串,它的原始值并没有改变。
3、基本数据类型的比较是值的比较
只要他们的值是相等的就认为他们是相等的。
var a = 1;
var b = 1;
console.log(a == b);//true
这里最好用严格等,否则会进行类型转换;
var a = 0;
var b = '0';
console.log(a == b);//true
console.log(a === b); //false
引用类型(数组】、对象、函数)
1、引用类型存放在堆内存
2、引用类型值可变
3、引用类型的比较是引用的比较
var a = [1,2,3];
var b = [1,2,3];
console.log(a === b);//false
比较两个对象的引用,是看两个引用是否指向同一个对象
基本数据类型与引用类型赋值比较
基本数据类型赋值是值的传递,先在栈内存中开辟一段内存,再把值赋值到新的栈中
var a = 10;
var b = a; a ++ ;
console.log(a); //
console.log(b); //
引用类型的赋值是传址,就是说赋值时是保存在栈中的变量的地址的赋值,这样两个变量指向同一个对象,所以两个变量之间会相互影响;
var a = {};
var b = a;
a.name = "qy";
console.log(a.name);//qy
console.log(b.name);//qy
b.age = 22;
console.log(a.age);//
console.log(b.age);//22
console.log(a === b);//true
赋值并不是浅拷贝,赋值和浅拷贝之间的区别
var obj1 = { //原始数据
"name" : "zhangsan",
"age" : "22",
"language" : [1, [2, 3], [4, 5]]
}
var obj2 = obj1;//赋值得到
var obj3 = shallowCopy(obj1);//浅拷贝得到
function shallowCopy(src) {
var dst = {};
for (var prop in src) {
if (src.hasOwnProperty(prop)) {
dst[prop] = src[prop];
}
}
return dst;
}
obj2.name = "lisi";//改变赋值得到的obj2的基本类型属性name,最后结果为原始数据里的属性也随之改变
obj3.age = "11";//改变浅拷贝得到的obj3的基本类型属性age,结果为原始数据的age属性并没有改变
obj2.language[1] = ['a', 'b'];//改变赋值得到的obj2的引用类型属性,结果为原始数据及由原始数据浅拷贝得到的obj3的language属性均被改变
obj3.language[2] = ['c', 'd'];//改变浅拷贝得到的obj3的引用类型属性,结果为原始数据及有原始数据赋值得到的obj2的language属性均被改变
console.log(obj1);//name:lisi,age:22,language:[1,[a,b],[c,d]]
console.log(obj2);//name:lisi,age:22,language:[1,[a,b],[c,d]]
console.log(obj3);//name:zhangsan,age:11,language:[1,[a,b],[c,d]]
结论:(首先需要明确深拷贝与浅拷贝都是针对引用类型而言的,基本数据类型不涉及到深拷贝与浅拷贝)
@1 引用类型的赋值是地址的传递,即赋值得到的新数据与原数据指向堆内存中的同一个对象,两者之间仍会互相影响;
@2 浅拷贝是通过创建一个新的对象(数组,对象),依次去拷贝对象的每一个属性,此时如果对象的属性为一个引用类型,那么拷贝过来的引用类型属性依然是指向与原数据的引用类型属性地址相同的一个对象,因此通过浅拷贝得到的新数据,与原数据的引用类型属性会相互影响;
@3 那么深拷贝是怎样的呢,深拷贝就是要做到新数据与原数据完全的互不影响(无论是基本类型还是引用类型);
三、如何进行深拷贝?
思路:递归调用浅拷贝方法,拷贝每一层次的对象属性;以下为zepto的extend方法
$.extend = function(target) {
var deep,
args = slice.call(arguments, 1);
if (typeof target == 'boolean') {
deep = target;
//target取第二个参数
target = args.shift();
}
//遍历后面的参数,都合并到target上面
args.forEach(function(arg){
extend(target, arg, deep)
})
return target;
}
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]不是数组也要初始化一下
if (isArray(source[key]) && !isArray(target[key])) {
target[key] = [];
}
//执行递归
extend(target[key], source[key], deep);
} else if (target[key] !== undefined) {
target[key] = source[key];
}
}
}
四、$.extend()方法(jquery的extend扩展方法)
1、原型:extend(dest,src1,src2,src3...);
含义:将src1,src2,src3...合并到dest中,返回值为合并后的dest
2、dest可为{}
var newSrc=$.extend({},src1,src2,src3...)//也就是将"{}"作为dest参数。
含义: 这样就可以将src1,src2,src3...进行合并,然后将合并结果返回给newSrc了;
例:
var result=$.extend({},{name:"Tom",age:21},{name:"Jerry",sex:"Boy"})
//结果为:
result={name:"Jerry",age:21,sex:"Boy"}
可见此方法中后面的参数如果和前面的参数存在相同的名称,那么后面的会覆盖前面的参数值。
3.重载原型1:省略dest参数,则该方法就只能有一个src参数,而且是将该src合并到调用extend方法的对象中去
例:
$.extend({
hello:function(){alert('hello');}
});
//将hello方法合并到jquery的全局对象中去
4、重载原型2extend(boolean,dest,src1,src2,src3...)
含义:第一个参数boolean代表是否进行深度拷贝,其他参数同上;
var result = $.extend(false, {}, {name: "a", location:{city: "beijing", pos: 1000}}, {age: 12, location:{city: "hanguo", age: 20}});
result= {name: "a", age: 12, location: {city: "hanguo", age: 20}}}
从JS的深拷贝与浅拷贝到jq的$.extend()方法的更多相关文章
- 【js】深拷贝和浅拷贝区别,以及实现深拷贝的方式
一.区别:简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,如果B没变,那就是深拷贝. 此篇文章中也会简单阐述到栈堆,基本数据类型与引用数据类型,因为这 ...
- JS实现深拷贝,浅拷贝的方法
在 JS 中,函数和对象都是浅拷贝(地址引用):其他的,例如布尔值.数字等基础数据类型都是深拷贝(值引用). 深拷贝 JSON.parse(JSON.stringify(src)):这种方法有局限性, ...
- js引用类型深拷贝、浅拷贝方法封装
引用类型的深拷贝.浅拷贝在前端领域一直是个很重要的知识点,不仅在业务中频繁使用,也是面试官们喜欢考的的知识点之一.本篇将封装引用类型的深拷贝.浅拷贝方法,并解决在封装过程中出现的问题. 一.浅拷贝 浅 ...
- JS JavaScript深拷贝、浅拷贝
浅拷贝:浅拷贝只是复制了内存地址,如果原地址中的对象改变了,浅拷贝出来的对象也会相应改变. 深拷贝:开辟了一块新的内存存放地址和地址指向的对象,原地址的任何对象改变了,深拷贝出来的对象不变. 浅拷贝数 ...
- js的深拷贝和浅拷贝
一.数组的深浅拷贝 在使用JavaScript对数组进行操作的时候,我们经常需要将数组进行备份,事实证明如果只是简单的将它赋予其他变量,那么我们只要更改其中的任何一个,然后其他的也会跟着改变,这就导致 ...
- js实现深拷贝和浅拷贝
浅拷贝: 思路----------把父对象的属性,全部拷贝给子对象,实现继承. 问题---------如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,不会开辟新栈,不是 ...
- js对象深拷贝与浅拷贝
浅拷贝 把a赋值给b,a与b指向相同的内存,修改b值,a也会跟着改变. var a = "aa"; var b = a; b = "bb"; 这个时候a也变成了 ...
- js对象深拷贝、浅拷贝
浅拷贝1 //浅拷贝1 let obj01 = { name: 'Lily', age: '20', time: ['13', '15'], person: { name: 'Henry', age: ...
- js 的 深拷贝 和 浅拷贝
http://www.cnblogs.com/yichengbo/archive/2014/07/10/3835882.html 类似于拷贝指针和 值? ...占坑先.
随机推荐
- JavaScript一看就懂(3)数组
定义数组 var a = [1, 2, 3]; typeof a; //"object", 数组是对象 a.length; //数组长度 相关操作 a[0]; //下标访问 a.p ...
- msql分区
确认mysql服务器是否支持分区表: show plugins; 如果能看到partition则表示能分区. HASH分区的特点: 根据MOD(分区键,分区数)的值把数据行存储到表的不同分区中 数据可 ...
- PHPStorm中对nodejs项目进行单元测试
安装必要的包 nodejs的单元测试最常用的是使用mocha包.首先确保你本地安装nodejs,之后安装mocha包. npm install mocha -g 然后还需要安装相关的断言工具,Node ...
- 要搞刷机!从它的尸体上踏过去!钢板云路由!WPR003N复活!成功启动OPENWRT
这是一个很鼓舞人心的标题,自从上一篇Aria2序之导言 00,成功的贴出两张开场图片,本来计划写它的开场引言 01,正好cp一个合格的导引(引导读起来有些奇怪),连续懒惰了好几天,突然想起了WPR00 ...
- linux 指令备忘
linux 指令备忘 1.ls [选项] [目录名 | 列出相关目录下的所有目录和文件 -a 列出包括.a开头的隐藏文件的所有文件 -A 通-a,但不列出"."和"..& ...
- Elasticsearch.Net、Nest批量插入BulkAll
demo地址:BulkAll 批量导入 实现目标:想要使用ElasticSearch的 .Net Api客户端NEST批量导入数据,并发异步高效的批量导入 NEST提供了BulkAll 不废话,上代码 ...
- 一次 C# 查詢數據庫 算法優化的案例
最近有次在修改某段程式時,發現一段程式算法看起來簡單. 但背後因為多次查詢數據庫,導致效能問題. 這段程式主要是利用 EPPLUS 讀取 Excel 資料,檢查資料是否已存在數據庫中,若有就將已存在的 ...
- ssh远程连接vm 安装的ubuntu
准备工作 安装包 vmware 虚拟机.xshell.ubuntu 1.软件安装比较简单,这里不做介绍 2.选择虚拟机连接方式 3.添加虚拟IP 配置 编辑->虚拟网络编辑器->选择vm ...
- 可以让你神操作的手机APP推荐 个个都是爆款系列
手机在我们的生活中显得日益重要,根据手机依赖度调查显示,69%的人出门时必带手机,20%的人经常在吃饭睡觉.上卫生间时使用手机:43%的人早上起床第一件事就是查看手机,不用多说,我们对于手机的依赖性越 ...
- android WebView技术笔记(存储技术)
作为刚刚开始工作的新手程序猿,各种知识还不算熟练,所以将学习到的知识记录一下以免以后忘记. WebView加载h5的知识现在可以说非常的常用,通过加载h5的网页可以在不更新app的情况下来更新app的 ...