JavaScript深入之参数按值传递

定义

在《JavaScript高级程序设计》第三版 4.1.3,讲到传递参数:

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

什么是按值传递呢?

也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。

按值传递

举个简单的例子:

1var value = 1; 2function foo(v) { v = 2; console.log(v); //2 } foo(value); console.log(value) // 1

很好理解,当传递 value 到函数 foo 中,相当于拷贝了一份 value,假设拷贝的这份叫 _value,函数中修改的都是 _value 的值,而不会影响原来的 value 值。

引用传递?

举个例子:

1var obj = { 2 value: 1 3}; 4function foo(o) { o.value = 2; console.log(o.value); //2 } foo(obj); console.log(obj.value) // 2

第三种传递方式

不急,让我们再看个例子:

1var obj = { 2 value: 1 3}; 4function foo(o) { o = 2; console.log(o); //2 } foo(obj); console.log(obj.value) // 1

例子一:

1var value = 1; 2function foo(v) { 3 v = 2; 4 console.log(v); //2 5} 6foo(value); 7console.log(value) // 1

内存分布如下:

改变前:

栈内存

堆内存

value

1

 

 

v

1

 

 

改变后:

栈内存

堆内存

value

1

 

 

v

2

 

 

例子二:

1var obj = { 2value: 1 3}; 4function foo(o) { 5 o.value = 2; 6 console.log(o.value); //2 7} 8foo(obj); 9console.log(obj.value) // 2

内存分布如下:

改变前:

栈内存

堆内存

obj,o

指针地址

{value: 1}

改变后:

栈内存

堆内存

obj,o

指针地址

{value: 2}

例子三:

1var obj = { 2value: 1 3}; 4function foo(o) { 5 o = 2; 6 console.log(o); //2 7} 8foo(obj); 9console.log(obj.value) // 1

内存分布如下:

改变前:

栈内存

堆内存

obj,o

指针地址

{value: 1}

改变后:

栈内存

堆内存

obj

指针地址

{value: 1}

o

2

 

关键点:

运算符=就是创建或修改变量在内存中的指向.
初始化变量时为创建,重新赋值即为修改.

首先一个非常简单的例子:

1var a = {b: 1};// a = {b: 1} 2var c = a;// c = {b: 1} 3a = 2;// 重新赋值a 4console.log(c);// {b: 1}

接着是上一段代码在内存中的分布:

a, c

{b: 1}

然后一步一步执行代码:

  1. 创建变量a指向对象{b: 1};
  2. 创建变量c指向对象{b: 1};
  3. a重新指向常量区的2;

常量区

a

 

2

c

{b: 1}

 

所以c从始至终都是指向对象{b: 1}.

1var value = 1; 2function foo(v) { 3 v = 2; 4 console.log(v); //2 5} 6foo(value); 7console.log(value) // 1

将案例一等价替换:

1var value = 1; 2function foo() { 3 var v = value; // 创建变量v指向value所指向的值 4 v = 2;// v重新指向另外的值 5 console.log(v); //2 6} 7foo(value); 8console.log(value) // 1,value从始至终都未改变指向.

案例三也可以这样替换.

接着分析案例二:

修改一下我的第一个例子:

1var a = {b: 1};// a = {b: 1} 2var c = a;// c = {b: 1} 3a.b = 2;// 重新赋值对象a中的属性b 4console.log(c);// {b: 2},// c也随着修改,从

在内存中的分布:

常量区

a,c

[[Object]]

 

b

 

1

执行完a.b = 2后:

常量区

a,c

[[Object]]

 

b

 

2

那么a,c从始至终都未改变指向,只是b改变了而已
第一张内存分布图将{b: 1}放入堆中,是为了大家更方便抓住重点

所以案例二等量替换为

1var obj = { 2 value: 1 3}; 4function foo() { 5 var o = obj; 6 o.value = 2;// 变量value改变了指向,而o并未改变 7 console.log(o.value); //2 8} 9foo(obj); 10console.log(obj.value) // 2 11 12 13 14 15不管是基本数据类型还是对象类型的,都是拷贝。前者拷贝值,后者拷贝地址值。
点赞
收藏

评论区

加载中...

相关推荐

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

java传值与引用的关系

       首先,我们必须要搞清楚的一件事是,不管java的参数类型是什么,一律传递的是参数的副本。也就是说每次传递参数的时候都会讲参数拷贝一份传递。1.基本数据类型:       对于基本的数据类型来说,java传递的是指的副本;也就是将数据拷贝一份以后传递。因此当函数返回的时候,不管在调用的函数中做了什么操作,基本数据类型的值都不会改变。

什么是高阶函数?

原文链接:什么是高阶函数?有两种情况都可以被定义为高阶函数,第一种是把函数作为参数传递给另外一个函数,第二种是把函数作为另一个函数的返回结果。就像我们平时调用函数,一般都是传递值类型或者对象和数组等参数,或者是函数返回结果是值类型或者是对象和数组,高阶函数

Java里的按值传递与引用传递

按值传递还是按引用传递这个在Java里面是经常被提起的问题,也有一些争论,似乎最后还有一个所谓的结论:“在Java里面参数传递都是按值传递”。事实上,这很容易让人迷惑,下面先分别看看什么是按值传递,什么是按引用传递,只要能正确理解,至于称作按什么传递就不是个大问题了。1:按值传递是什么指的是在方法调用时,传递的参