js复制变量值以及参数传递

899 阅读3分钟

在js中,类型分为基本类型和引用类型。基本类型复制变量称为值传递,引用类型复制变量成为引用传递。

1、基本类型复制

var num = 10
var numCopy = num
console.log(numCopy); // 10
console.log(num); //10
num = 20
console.log(numCopy); // 10
console.log(num); // 20

在代码中可以看到,num和numCopy是互不影响的。 在基本类型复制过程中,复制对象复制被复制对象的时候,复制对象本身会创建一个新的值,然后把复制的值分配到新变量的位置上,也就是说,在NumCopy复制num的时候,numCpoy会创建一个新的值,然后把num的值复制放到numCopy新分配的位置上。

2、引用类型复制

// 引用类型中,一个变量复制另一个变量,实际上指针指向的是同一个变量
var object = {
  name:'hsy',
  age: 22
}
var obj = object
console.log('obj',obj); //{name: "hsy", age: 22}
console.log('object',object); //{name: "hsy", age: 22}
obj.name ='wyx'
console.log('object',object); //{name: "wyx", age: 22}
console.log('obj',obj);//{name: "wyx", age: 22}

从代码中可以看出object和obj是互相影响的,在引用类型中,一个变量复制另一个变量,值复制到新的分配的位置上去了,但是本质上指针还是指向同一个指针。

3、参数传递

在js中,应该是在ES中,所有的参数传递都是按值传递。但是疑惑的是为什么在访问变量的时候有按值传递和引用传递,但是在参数传递中全部按值传递。 实际上,在向参数传递基本类型的数值的时候,被传递的值被复制到一个局部变量里面。传递引用类型的数据的时候,会把传递值的内存地址复制到一个局部变量,因此这个局部变量的变化会反映在函数的外部。

3.1 值类型参数传递

// 1、基本类型参数
function sum (num) {
  num += 10
  return num
}
const count = 10
console.log(sum(count)); // 10
console.log(count) // 10

count并没有因为num的改变而改变数据。

3.2 引用类型参数传递

function setName (obj) {
  obj.name = 'hsy'
}
var p = new Object()
console.log(p); // {}
setName(p)
console.log(p); // {name: hsy}

上面代码创建了一个对象,并将变量保存在p中,然后这个对象被传递到setName()函数之中就被复制给了obj,在函数内部,obj与p引用的是同一个对象,所以,当函数内部obj添加name属性之后,外部的p也会有所反应。这里有一个误区就是局部作用域修改之后全局作用域也会修改,就说明是参数是按照引用类型传递的,为了证明这一想法是错误的,我这边做了一点小修改:

  function setDoubleName (obj) {
  obj.name ='wyx'
  obj = new Object()
  obj.name = 'xtt'
}
let p1 = new Object()
console.log(p1);  // {}
setDoubleName(p1) // 
console.log('p1',p1); //p1{name: "wyx"}

在这段代码里面可以看到p1最终输出的是{name:"wyx"},如果说是引用类型的话,在下面obj.name = 'xtt'的时候,外面的p1是能监测到obj.name的改变,但是并没有改变,这说明即使在函数内部修改了参数的数值,但是原始的引用仍然保持未读。 实际上,当在函数内部重写obj时,这个变量引用的就是一个局部变量了,而且这个局部变量会在函数执行完毕之后立即被销毁。

在这里可以把ES函数的参数想象成局部变量