js的值引用和地址引用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js的值引用和地址引用相关的知识,希望对你有一定的参考价值。

参考技术A number 类型

        var a = 1;

        var b = a;

        b++;

        console.log(a);  //1

        console.log(b);  //2

字符串类型

        var q = 'copy';

        var s = q;

        s += '1';

        console.log(q); //copy

        console.log(s); //copy1

布尔类型

        var e = false;

        var w = e;

        w = true;

        console.log(e)  //false

        console.log(w)  //true

数组

        splice  截取  会改变原数组

        //地址的引用  浅拷贝

        var array = [1,2,3,4,5];

        var newArray = array;

        var thArray = newArray.splice(1,3);

        console.log(thArray);  //[2,3,4]

        console.log(newArray);  //[1,5]

        console.log(array);    //[1,5]

        //循环到原始类型进行深拷贝

        var  arr = ['a','b','c','d','e'];

        var  newArr = [];

        for(var i=0;i<arr.length;i++)

            newArr.push(arr[i]);

       

        var thArr = newArr.splice(1,3);

            console.log(thArr);  //["b", "c", "d"]

            console.log(newArr);  //["a", "e"]

            console.log(arr);  //["a", "b", "c", "d", "e"]

         对象

        //地址的引用  浅拷贝

        var obj = name:'abc',id:'1';

        var newObj = obj;

        newObj.name='abcde';

        console.log(obj);  //name:'abcde',id:'1'

        console.log(obj);  //name:'abcde',id:'1'

        //循环到原始类型进行深拷贝

        var object = name:'321',id:'1';

        var newObject= ;

        for (var j in object)

            newObject[j]=object[j]

       

        newObject.name='abcde';

        console.log(newObject);  //name:'abcde',id:'1'

        console.log(object);      //name:'321',id:'1'

数字   字符串   布尔类型   为原始类型,是值引用

数组   对象类型 为地址引用

值引用为深拷贝

地址引用循环到原始类型可进行深拷贝

        var nameArray = ['张三','李四'];

        var descArray = ['张三是男生','李四也是男生'];

        var allArray = [];

        var tableObj=;

        for(let i=0; i<nameArray.length;i++)

            tableObj.name=nameArray[i];

            tableObj.desc=descArray[i];

            allArray.push(tableObj)

       

        console.log(allArray)          //name: "李四", desc: "李四也是男生"

                                        //name: "李四", desc: "李四也是男生"

       var nameArray = ['张三','李四'];

        var descArray = ['张三是男生','李四也是男生'];

        var allArray = [];

        for(let i=0; i<nameArray.length;i++)

            var tableObj=;

            tableObj.name=nameArray[i];

            tableObj.desc=descArray[i];

            allArray.push(tableObj)

       

        console.log(allArray)          //name: "张三", desc: "张三是男生"

                                        //name: "李四", desc: "李四也是男生"

js传参是按值传递还是按引用传递?

 数据类型

基本数据类型

number、string、boolean、null、undefined   基本数据类型的值保存在栈中;

引用数据类型

array、object、function 等对象,引用类型的数据保存分为两部分:

  • 地址
  • 值  

其中栈中是保存地址的引用,堆中保存真正的值  如

技术分享

 

什么是按值传递?什么是按引用传递?

按值传递(call by value):函数的形参是被调用时所传实参的副本,修改形参的值并不会影响实参。

按引用传递(call by reference)时,函数的形参接收实参的隐式引用,而不再是副本。这意味着函数形参的值如果被修改,实参也会被修改,同时两者指向相同的内存地址。

Js传递方式

参数是基本数据类型:

1     var a = 10;
2     function add(a) {
3         a = 20;
4         console.log(a);//20
5     }
6     add(a);
7     console.log(a);//10

变量a在add 内部改变了值,并没有影响到外部的a变量;

参数是引用类型:

1 //引用类型
2     var person = {name: ‘joel‘, age: 11}
3     function foo(o) {
4         o.name = ‘alen‘;//改变对象的值
5         o = {name: ‘elire‘}//改变对象的地址
6         console.log(o.name); //elire
7     }
8     foo(person);
9     console.log(person.name);//alen

如果是按照引用传递,传进去的o对象跟外部的person对象指向的内存应该是同一个,但是foo()内部o.name 是elire,外部的person.name 是alen,所以尽管是引用类型数据传递的时候也不是按引用传递;

继续看下面demo:

 1     var v1 = []
 2     var v2 = {};
 3     var v3 = {};
 4     function demo1(v1, v2, v3)
 5     {
 6         v1 = [1];
 7         v2 = [2];
 8         v3 = {a:3}
 9     }
10     demo1(v1, v2, v3);
11     console.log(v1); // 空白
12     console.log(v2); // [object Object]
13     console.log(v3.a); // undefined

由此可见:v1、v2、v3 都没有被改变,v1 仍然是零个元素的数组,v2、v3 仍然是空白的对象。即引用类型数据也是按照值传递的,先是拷贝了栈中的地址,然后在demo1()内部改变了地址的指向。

但是引用类型按值传递与基本类型数据按值传递还是有区别的。

基本数据类型,如数字、字符串是把值直接复制进去了,而引用类型 如数组、对象是把变量地址复制进去。

前面我们让 v1、v2、v3 作为参数进入函数后,就有了地址副本,这些地址副本的指向和外面的 v1、v2、v3 的地址指向是相同的。但我们为 v1、v2、v3 赋了值,也就是说我们把地址副本的指向改变了,指向了新的数组和对象。这样内部的 v1、v2、v3 和外部的 v1、v2、v3 就完全断了。
如果我们不赋新值,而是直接操作它,那么传进去的仍然是和外面的 v1、v2、v3 指向的同一块数组或对象,因为我们没有改变他们的指向。

如:

 1     var v1 = []
 2     var v2 = {};
 3     var v3 = {a:0};
 4     function demo2(v1, v2, v3)
 5     {
 6         v1.push (1);
 7         v2.a = 2;
 8         v3.a = 3;
 9     }
10 
11     demo2(v1, v2, v3);
12     console.log(v1); // 1
13     console.log(v2.a); // 2
14     console.log(v3.a); // 3

总结

基本数据类型,如数字、字符串是把值复制进去,而引用类型 如数组、对象是把变量地址复制进去,

如果没有改变传进去的地址指向,那么它们都是指向同一个内存地址;

如果改变了地址指向那么它们跟外部的对象是两个独立的对象,互不干扰;

 

以上是关于js的值引用和地址引用的主要内容,如果未能解决你的问题,请参考以下文章

js按值传递和按引用传递

仔细看看,会有收获。js深浅拷贝

仔细看看,会有收获。js深浅拷贝

仔细看看,会有收获。js深浅拷贝

仔细看看,会有收获。js深浅拷贝

js传参是按值传递还是按引用传递?