JavaScript高级程序设计4.1.3(170页)中有这么一句话:访问变量有按值和按引用两种方式。
这句话怎么理解?什么是按值?什么是按引用?
JavaScript高级程序设计4.1.3(170页)中有这么一句话:访问变量有按值和按引用两种方式。
这句话怎么理解?什么是按值?什么是按引用?
在最新的 ECMAScript 标准中,定义了 7 种数据类型,其中 string number boolean null undefined symbol 为原始数据类型,object为引用数据类型
值针对的是基本类型。引用针对的是对象,引用传递的是对象的地址(想想C语言的指针)。对于引用的值(对象),可以改变内部状态。
值传递示例:
function hi(a) {
a = 12;
console.log("in func: " + a );
}
a = 24;
hi(a);
console.log("out of func: " + a );
输出:
in func: 12
out of func: 24
引用示例:
function hi(a) {
a.push(44);
console.log("in func: " + a );
}
a = [2,33];
hi(a);
console.log("out of func: " + a );
输出:
in func: 2,33,44
out of func: 2,33,44
按值访问相当于是将原数据的值进行一次拷贝,给新的变量,原变量发生改变后,按值访问的不会变化。一般是string,number这样的基本类型。
var a = 1;
var b = a;
alert(a+";"+b);//1;1
a = 2;
alert(a+";"+b);//2;1 b不会发生改变,因为是按值访问
按引用是指在内存区内只有一份,新的变量只是拥有一个指向它的指针,一旦内存区内的内容发生变化,所有指向它的引用都将发生变化,一般是对象,包括用户自定义对象和内置对象,Array和Function。
var a = {name: "Zoe"};
var b = a;
console.log(a.name);//Zoe
console.log(b.name);//Zoe
a.name = "Alex";
console.log(a.name);//Alex
console.log(b.name);//Alex 按引用访问,指针指向的区域已经被更改
8 回答5.8k 阅读✓ 已解决
9 回答9.1k 阅读
6 回答4.7k 阅读✓ 已解决
5 回答3.5k 阅读✓ 已解决
4 回答7.9k 阅读✓ 已解决
7 回答9.6k 阅读
5 回答7.1k 阅读✓ 已解决
尽信书不如无书。
我恰好今天刚看了书中这个地方。我觉得书里说的不准确,至少不清楚。
首先要弄清楚一些概念:变量、值、值的类型、引用、对象。
如果这些概念没搞清楚,就没办法讨论这个问题。
变量:变量就是一个定义在某个作用域的名字(name),它是一个identifier。它绑定(bind)了一块内存。
值:值就是变量绑定的那块内存里面存放的数据。至于存放的数据的具体代表什么(含义是什么),暂且不管。但是本质上就是一段二进制数。
值的类型:即变量绑定的那块内存里放的数据应该如何去解释,或者说如何解码。在JS中值的类型有很多种,但是可以归结成两类:基本类型和引用类型。基本类型就是说:变量绑定的那块内存里放的数据的含义就是它看起来的那个样子。引用类型就是说:变量绑定的那块内存里放的数据,并不是我真正想要的数据,它是一个元数据、一个地址,一个指向我真正想用的数据的位置的指针。
总结一下就是:变量是一个名字,它绑定一块存储空间,这个空间要么放数据,要么放数据的地址(或者某种引用)。
引用:见上面。
对象:上面说的那些不能被变量直接绑定,而是要通过引用来间接绑定的数据就是对象。而且对象数据与非变量数据相比有一个特点,即它是有内部结构的,即属性。
所以在JS中变量有两种模式:
名字->数据
名字->数据(引用)->数据(对象)
接下来可以讨论问题了。
问题是讨论JS中变量“访问”有几种类型?按值和按引用?
那么,我们应该首先定义一下什么是“访问”?不知道,因为没有一个地方来给出一个标准定义。但是我猜访问的意思大概是:通过变量去取得你真正想要的数据。假设是这个意思的话,那么很简单,确实是两种,分别对应上面两种变量模式。即基本类型数据就是直接取变量的“值”;而对象类型的数据要通过取变量的值代表的引用,然后再取它指向的对象。
但是,如果不限于“访问”,我们来讨论一下对变量的“操作”呢?
首先来看一下,对一个变量的操作有几种类型。
读
写
属性访问
读:很多操作符都涉及到对变量的读,比如加减乘除等算术运算、关系运算、逻辑运算和位运算等等。这些运算大都是针对基本类型数据(或者先将操作数转为基本类型)的,所以是“按值”操作的。
写:能改变一个变量的值的操作只要三种,即自增、自减和赋值(包括+=这类)。显然也都是“按值”。那么赋值操作呢?也是按值,因为赋值时只是将变量绑定的内存拷贝到另一个变量绑定的内存中,与内存中存的数据的含义无关。
属性访问:属性访问是对对象来说的,只有对象才有属性。(当然JS比较特殊的一点是,对基本类型数据也可以访问属性,这是因为在这里JS执行引擎会把基本类型数据包装成一个对象,这种情况暂不讨论)显然这里需要访问对象的内部状态,要通过引用链接到对象。所以这种情况是按引用。
说了这么多,到后面觉得有些凌乱,有些不严谨了。
试着总结一下:
对于对象数据才有的操作,是按引用。比如属性访问。
对于基本类型数据才有的操作,是按值。比如加减乘除。
对于所有类型数据都有的操作,并且操作的语义与操作数是什么类型无关的情况,按值。比如赋值、传参等。
敬请指正。