一、堆内存与栈内存

  堆和栈都是内存中划分出来的用来存储的区域,栈为自动分配的内存空间,它由系统自动释放,堆为动态分配的内存,大小不定也不会自动释放。

二、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(true,{}, {name: "a", location:{city: "beijing", pos: 1000}}, {age: 12, location:{city: "hanguo", age: 20}})
result={name: "a", age: 12, location: {city: "hanguo", pos: 1000, age: 20}};

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()方法的更多相关文章

  1. 【js】深拷贝和浅拷贝区别,以及实现深拷贝的方式

    一.区别:简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,如果B没变,那就是深拷贝. 此篇文章中也会简单阐述到栈堆,基本数据类型与引用数据类型,因为这 ...

  2. JS实现深拷贝,浅拷贝的方法

    在 JS 中,函数和对象都是浅拷贝(地址引用):其他的,例如布尔值.数字等基础数据类型都是深拷贝(值引用). 深拷贝 JSON.parse(JSON.stringify(src)):这种方法有局限性, ...

  3. js引用类型深拷贝、浅拷贝方法封装

    引用类型的深拷贝.浅拷贝在前端领域一直是个很重要的知识点,不仅在业务中频繁使用,也是面试官们喜欢考的的知识点之一.本篇将封装引用类型的深拷贝.浅拷贝方法,并解决在封装过程中出现的问题. 一.浅拷贝 浅 ...

  4. JS JavaScript深拷贝、浅拷贝

    浅拷贝:浅拷贝只是复制了内存地址,如果原地址中的对象改变了,浅拷贝出来的对象也会相应改变. 深拷贝:开辟了一块新的内存存放地址和地址指向的对象,原地址的任何对象改变了,深拷贝出来的对象不变. 浅拷贝数 ...

  5. js的深拷贝和浅拷贝

    一.数组的深浅拷贝 在使用JavaScript对数组进行操作的时候,我们经常需要将数组进行备份,事实证明如果只是简单的将它赋予其他变量,那么我们只要更改其中的任何一个,然后其他的也会跟着改变,这就导致 ...

  6. js实现深拷贝和浅拷贝

    浅拷贝: 思路----------把父对象的属性,全部拷贝给子对象,实现继承. 问题---------如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,不会开辟新栈,不是 ...

  7. js对象深拷贝与浅拷贝

    浅拷贝 把a赋值给b,a与b指向相同的内存,修改b值,a也会跟着改变. var a = "aa"; var b = a; b = "bb"; 这个时候a也变成了 ...

  8. js对象深拷贝、浅拷贝

    浅拷贝1 //浅拷贝1 let obj01 = { name: 'Lily', age: '20', time: ['13', '15'], person: { name: 'Henry', age: ...

  9. js 的 深拷贝 和 浅拷贝

    http://www.cnblogs.com/yichengbo/archive/2014/07/10/3835882.html 类似于拷贝指针和 值?  ...占坑先.

随机推荐

  1. C#反射调用方法实例

    下面是两个反射的实例 案例1: 动态调用类中的方法.传入参数,并获得返回值. xxxx:类名 Event:类中的方法 pra1,pra2,pra3:方法对应的入参 DoRet:方法返回的执行结果 Ty ...

  2. Mybatis+mysql批量插入性能分析测试

    前言 今天在网上看到一篇文章(后文中的文章指的就是它) https://www.jianshu.com/p/cce617be9f9e 发现了一种有关于mybatis批量插入的新方法,而且看了文章发现我 ...

  3. 103 - kube-scheduler源码分析 - 调度算法-寻找predicates和priorities

    scheduler的主要逻辑是predicate和priority,前者回答哪些节点可以运行pod的问题,后者回答哪个节点更合适运行pod的问题.今天我们的任务是:从主函数出发,寻找predicate ...

  4. RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2->WinForm版本重构岗位授权管理界面更规范、高效与美观

    岗位(职位)管理模块主要是针对组织机构的岗位(职位)进行管理,包括:增加.修改.删除.移动.对岗位设置用户,设置岗位的权限等.岗位管理在企业应用中是一个普遍应用的模块,也属于其他业务应用的基础.合理的 ...

  5. 4.4管道和中间件介绍「深入浅出ASP.NET Core系列」

    希望给你3-5分钟的碎片化学习,可能是坐地铁.等公交,积少成多,水滴石穿,谢谢关注. 管道流 我们知道一个管道可以有一个或多个中间件,而中间件的职责是根据HttpContext处理HTTP请求,然后往 ...

  6. #3 Python面向对象(二)

    前言 上一节主要记录面向对象编程的思想以及Python类的简单创建,这节继续深入类中变量的相关知识,Here we go! Python中类的各种变量 1.1 类变量 类变量定义:在类中,在函数体(方 ...

  7. 【转载】java 中变量的存储位置

    原文链接点这里,感谢博主分享 * 寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. * 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出 ...

  8. [TCP/IP] 传输层-TCP和UDP的使用场景

    传输层-TCP和UDP应用场景 TCP(传输控制协议) 需要将要传输的文件分段传输,建立会话,可靠传输,流量控制 UDP(用户报文协议) 一个数据包就能完成数据通信,不需要建立会话,不分段,不用流量控 ...

  9. day09 css

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  10. Java 8中Stream API学习笔记

    1)函数式编程的优势和劣势分别是什么?优势:①不可变性 ②并行操作 ③执行顺序更灵活 ④代码更加简洁纯粹的函数式编程,变量具有不可变性,同一个参数不会在不同场景下得出不同的结果,因此大大增强了系统的稳 ...