首页 > 设计 > WEB开发 > 正文

按值传递和按地址传递

2019-11-04 08:04:26
字体:
来源:转载
供稿:网友

按值传递和按地址传递

变量分为基本类型(值型)和引用类型变量. 基本数据类型包括数字,字符串,布尔,null,undefined这些, 引用数据类型包括object(Object,Array, RegExp, Date, Math...), 函数.

如果将基本类型的值赋值给变量, 变量会将这个值的本身保存起来:

var a = 123; // 将数值123赋给变量avar b = a;  // 将变量a的值(数值123)赋给变量b

此时如果将变量b自增操作, 变量a的值不会受到影响;

b++;console.log(b);   // 124console.log(a);   // 123

如果将对象赋值给变量, 实际上是把对象的引用赋值给了变量; 变量保存的只是对象在内存中的地址.

var a = {x:1, y:3};  var b = a;  // 将对象的地址赋值给b

上面的代码, 变量a和b都指向相同的地址, 也就是引用了同一个对象; 如果对b所引用的对象进行改变, 这一改变也会体现在变量a之中;

b.x++;console.log(b.x); // 2console.log(a.x); // 2

接下来看这段代码:

var a = {x:1,y:2};var b = a;  // b和a指向同一个对象a = {x:2,y:1};   // a重新赋值,指向另一个对象console.log(b.x);

这段代码通过赋值运算符将a重新赋值, 于是a不再引用一开始的对象, a与b之间的联系被切断, 因此不会再互相影响.

函数的参数(按值传递)

ECMAScript中所有函数的参数都是按值传递的;

function swap(a,b) {  var tmp = a;  a = b;  b = temp;}var one = 1;var zero = 0;swap(one, zero);console.log(one, zero); // one与zero的值没有发生改变

把函数外部的值赋值给函数内部的参数, 相当于把值从一个变量复制给另一个变量一样. 函数的参数a和b可以理解成函数的私有变量,它们被赋于了全部变量one和zero的值, 然而这两个函数内部变量赋值的改变影响不到全部变量one和zero.

如果使用对象, 情况又会有所不同:

function setName(obj) {  obj.name = "Nicolas";}var person = new Object();setName(person);console.log(person.name);

以上代码创建了一个对象, 将对象保存到变量person中. 变量person被传递到函数setName后被复制给了obj, 这一步可以理解成, 对象的引用地址被复制给了obj. obj和person引用了同一个对象. 于是, 当在函数内部为obj添加name属性后, 函数外部的person也会有所反映.有的人会认为如果把引用类型数据作为参数, 参数就是按引用传递的. 其实无论传递了什么, 全都是按值传递. 改写下上面的代码:

function setName(obj) {  obj.name = "Nicolas";  obj = new Object();  obj.name = "Greg";}var person = new Object();setName(person);console.log(person.name); // "Nicolas"

这个例子中在函数内部创建了一个新的object对象并将name属性设置为"Greg", 如果person是按引用传递的, person就会被修改了name属性为"Greg"的新对象; 而事实上并没有. 说明即使在函数内部修改了参数的值, 也影响不到原始引用. 实际上函数内部重写的obj是引用了一个只在函数局部作用域中存在的对象, 函数执行完毕后这个对象就会被销毁.

本文参考了javascript高级程序设计第3版和Javascript编程全解(然而写得比原书乱多了...)


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表