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的值引用和地址引用的主要内容,如果未能解决你的问题,请参考以下文章