美文网首页
js的值传递和引用传递

js的值传递和引用传递

作者: FFriday | 来源:发表于2017-08-06 20:10 被阅读190次

我们知道js中那些是值类型,那些是引用类型,这是必须要搞清楚。
JavaScript中的值类型:数值、布尔值、null、undefined
JavaScript中的引用类型:对象、数组、函数

堆栈

栈(stack)
由操作系统自动分配释放 ,存放函数的参数值局部变量的值等。其操作方式类似于数据结构中的栈。一种先进后出的数据结构。

堆(heap)
动态分配的内存,大小不定也不会自动释放。队列优先,先进先出。

值类型是存放在栈中的基本类型,对象数据则是在堆中创建并在栈中保留对象在堆中的地址。我们从下面的例子来理解

    var a = [1,2,3,4,5];
    var b = a;
    var c = a[0];
数据在内存中的存储示意图(图片来自‘小辉_Ray’的博客)

通过变量在内存中的存储我们可以看出来,所有的变量都是在栈内存中存在的,不同的是值类型存放的是值本身,引用类型存放的是指向堆内存对象的地址。
基本类型与引用类型最大的区别实际就是传值与传址的区别。


var a =1;
var array = [1,2,3];
var object = {a:1,b:2,c:3};

function reassign(num,arr,obj){
    //将参数重新赋值
    num = '';
    //arr 是array对象的引用拷贝,我们把这个引用重新赋值,这时的arr不在指向array所指向的对象,而是指向新的空数组
    //所以这时候我们再对arr进行操作,将不会影响array。
    //obj同理
    arr = [];
    arr.push(123);
    obj = '';
}
function operate(num,arr,obj){
    num = 2;
    arr.push(4);
    obj.test = 'test';
    // 我们直接对传递的参数进行操作,
    // 参数num是值类型,传递的是参数a的值拷贝,所以我们对num进行操作不会影响外层的a变量
    // arr,和obj,一个是数组,一个是对象,都是引用类型,传递的是对象地址的拷贝,我们对它的操作也会影响到外层变量的值,因为他们都指向相同的堆对象。
}


reassign(a,array,object);
console.log(a);      // 1
console.log(array);  // [1,2,3]
console.log(object); // {a:1,b:2,c:3}


operate(a,array,object);
console.log(a);      // 1
console.log(array);  // [1,2,3,4]
console.log(object); // {a:1,b:2,c:3,test:'test'}

对象的拷贝

js 深拷贝 vs 浅拷贝
浅拷贝

//如果对象的属性是引用类型,对对象的属性进行拷贝时,拷贝的只是对象属性的引用
function Copy(object) {
    var temp = {};
    for (var property in object) { 
      temp[property] = object[property];
    }
    return temp;
}

var obj = {}  
obj.a = "abc";
obj.b = [1,2];

var copyObj = Copy(obj);

console.log(copyObj);  // { a: 'abc', b: [ 1,2] }

copyObj.b.push(3); //这里向copyObj的b属性中push一个值,原始的obj对象也会受到影响,因为数组是引用类型

console.log(obj);  //{ a: 'abc', b: [ 1, 2, 3 ]}

深拷贝

// 实际编码中,很多时候浅拷贝并是我们想要的,我们希望拷贝完成后的对象和原对象不再有任何关联。
// 深拷贝
function Copy(source, target) {
    var target = target || {};
    for (var i in source) {
      if (typeof source[i] === 'object') { //这里有个疑问, 如果对象的属性是函数呢?
         target[i] = (source[i].constructor === Array) ? [] : {};
         Copy(source[i], target[i]);
      } else {
         target[i] = source[i];
      }
    }
    return target;
}  

var obj = {}  
obj.a = "abc";
obj.b = [1,2];
obj.c = function(){};

var copyObj = Copy(obj);

copyObj.b.push(3); //这里向copyObj的b属性中push一个值,原始的obj对象也会受到影响,因为数组是引用类型

console.log(copyObj);  // { a: 'abc', b: [ 1,2] }
console.log(obj);  //{ a: 'abc', b: [ 1, 2, 3 ]}

相关文章

  • JS是按值传递还是按引用传递?

    JS是按值传递还是按引用传递? 按值传递 VS. 按引用传递 探究JS值的传递方式 按共享传递 call by s...

  • js的值传递和引用传递

    我们知道js中那些是值类型,那些是引用类型,这是必须要搞清楚。JavaScript中的值类型:数值、布尔值、nul...

  • Day12-Java

    值传递和引用传递 值传递是值的拷贝, 引用传递是引用的拷贝 String 类型是引用类型, new String ...

  • Java中的参数传递

    为了便于理解,会将参数传递分为按值传递和按引用传递。按值传递是传递的值的拷贝,按引用传递传递的是引用的地址值,所以...

  • Java所有参数-对象引用及基本类型值--都是值传递

    前言 当前主要存在两种传递方式,值传递和引用传递,先简单介绍值传递和引用传递值传递(pass by value)是...

  • 第四题

    写出输出值,并写出原因 按值传递和按引用传递 函数的参数的按值传递的 js之所以有这样设计,是因为:按值传递的类型...

  • JavaScript深入之参数按值传递

    除了按值传递、引用传递,还有第三种传递方式 —— 按共享传递(JS应该是共享传递,没有所谓的引用传递) 共享传递是...

  • js中经典问题讲解

    1.传递参数是按值传递还是按引用传递? 苏墨橘的回答JS是按值传递还是按引用传递? 2.执行环境及作用域 《jav...

  • Dart是值传递还是引用传递

    结论:Dart是值传递。 我们先看值传递和引用传递的定义: 值传递和引用传递,属于函数调用时参数的求值策略(Eva...

  • JS 中的值传递和引用传递

    1、值传递(值拷贝的传递) number,string,boolean,null,undefined,Date,f...

网友评论

      本文标题:js的值传递和引用传递

      本文链接:https://www.haomeiwen.com/subject/lqawlxtx.html