从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 类似于拷贝指针和 值? ...占坑先.
随机推荐
- ubuntu 安装 npm、nodejs 各种问题
nodejs let notifier = require('update-notifier')({pkg}) 报错 先卸载nodejs,然后安装稳定最新版 # apt-get remove node ...
- 深入解读MySQL8.0 新特性 :Crash Safe DDL
前言 在MySQL8.0之前的版本中,由于架构的原因,mysql在server层使用统一的frm文件来存储表元数据信息,这个信息能够被不同的存储引擎识别.而实际上innodb本身也存储有元数据信息.这 ...
- Java Web开发模式
一 Java Web开发模式的变迁 1 最初的Java web服务器端编程技术是Servlet,利用Servlet就可以开发出一个Web应用程序. 2 为了解决Servlet缺陷,SUN推出了JSP技 ...
- Springboot 系列(七)Spring Boot web 开发之异常错误处理机制剖析
前言 相信大家在刚开始体验 Springboot 的时候一定会经常碰到这个页面,也就是访问一个不存在的页面的默认返回页面. 如果是其他客户端请求,如接口测试工具,会默认返回JSON数据. { &quo ...
- 为什么单线程的Redis这么快?
一. Redis简介 Redis是一个开源的内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(li ...
- JavaScript局部变量变量和函数命名提升
之前接触了一些javascript局部变量命名提升的问题但是一直没有总结今天特地好好总结一下 变量提升 一个变量的作用域是程序源代码中定义的这个变量的区域.全局变量拥有全局作用域,在javascrip ...
- 洛谷P3366 【模板】最小生成树(Boruvka算法)
题意 题目链接 Sol 自己yy着写了一下Boruvka算法. 算法思想很简单,就是每次贪心的用两个联通块之间最小的边去合并. 复杂度\(O(n \log n)\),然鹅没有Kruskal跑的快,但是 ...
- SlidingMenu的使用详解
前言- 最近自己在做一个Android的程序,需要用到一个侧滑的菜单,发现了SlidingMenu这个开源项目.简单实用,但是实战的时候遇到了许多小问题,今天来记录一下. SlidingMenu的使用 ...
- 一分钟了解Allegro导入DXF文件
Allegro, pads,PCB线路板设计,小北PCB 很高兴与大家分享一分钟了解Allegro导入DXF文件的方法,请问您们,刚学习这个软件时,您是否遇到过同样的问题呢?应该我们每一个刚学习者都会 ...
- dbgrideh 哪些行被选中了
在dbgrideh中允许选择多行,如何知道哪些行被选中是个BOOKMARK类型的属性.SelectedRows: TBookmarkListprocedure TForm1.Button1Click( ...