JS的方法参数传递(按值传递)

出处:JavaScript高级程序设计(第三版)第四章——变量、做用域和内存问题git

一句话总结

JS的方法参数是按值传递github

前提

ES变量分为两种数据类型的值:基本类型和引用类型函数

基本类型存储

基本类型的值在申请内存时是固定大小,因此保存在栈内存,故在复制基本类型变量时也是在栈内存中新开辟一分内存空间进行存储ui

引用类型存储

而引用类型变量的值大小不固定,且可任意改动,引用类型变量的本质是指向某一块内存区域的指针变量,故引用类型变量存储在内存自由分配的堆内存中,在对引用变量做直接复制(从新赋值)时也只是将新的变量指向相同的一片内存区域(即两个指针指向同一片堆内存空间)spa

引用类型探析

引用类型的值是存放在内存中的对象,但因为JS语言不容许直接访问内存中的位置(即不能直接操做对象的内存空间),故操做对象时实际是在操做对象的引用,而不是直接操做实际的对象自己(即引用类型的值是按引用访问的,这个引用能够理解为对象的句柄)设计

特别地

不少语言对于字符串是以对象形式进行表示,故为引用类型变量,但ES不是指针

详解

ES中全部函数(方法)的参数都是按值传递的,即调用一个方法时,是将调用该方法时传入该方法的参数的复制给函数内部的参数(将实参的值复制给形参)code

具体分类

JS在访问变量时有按值和按引用两种方式,但参数只会按值传递对象

向参数传递基本类型的值

被传递的值会被复制给一个局部变量(这个局部变量就是形参,在ES中就是arguments对象的一个元素)blog

实例
function addTen(num) {
  num += 10;
  return num;
}
var count = 20;
var result = addTen(count);
// 看有没有影响到原变量
alert(count);
alert(result)
复制代码

执行结果

20
30
复制代码

向参数传递引用类型的值

JS会把被传递的值的地址复制给一个局部变量,由于复制的是地址,因此在函数执行时,函数形参在函数内部改变时会影响到函数外部的该引用变量的值,由于两个地址指向同一片内存区域,但在函数执行结束,函数内部的局部变量被销毁,影响即会消失

实例
function setName(obj) {
  obj.name = 'tom';
}
var person = new Object();
setName(person);
// 当把person传递给setName时,obj和person都指向相同的内存,因此对obj所指向的内存区域修改会影响到person
alert(person.name);
复制代码

执行结果

tom
复制代码
分析

由于person指向的对象在堆内存中只存在一个,而且是全局对象

求证参数是按值传递而不是按引用传递

function setName(obj) {
  obj.name = 'tom';
  obj = new Object();
  obj.name = 'jerry';
}
var person = new Object();
setName(person);
// 当把person传递给setName时,obj和person都指向相同的内存,因此对obj所指向的内存区域修改会影响到person
alert(person.name);
复制代码

执行结果

tom
复制代码
结论

函数内部从新生成的对象obj,并对其新赋值jerry并无改变函数外部person对应的属性值

若是向引用类型参数赋值是按引用赋值,那么person的name应该变为jerry,由于假设形参obj拿到的是person的引用,而不是person引用的值,那么当函数内部生成新对象,并对obj进行从新指向时,形参obj的指向改变,外部的person的指向也应该改变,可是结果证实alert(person.name)显示的依旧是tom,因此即便函数参数是引用类型,也是按值传递

而实际上在函数内部重写obj时,这个变量引用的是一个局部对象变量,该局部对象会在函数执行完毕之时销毁

原文自 我的github博客,欢迎star

相关文章
相关标签/搜索