javascript中值传递与值引用的研究
今天重新看了一下《javascript高级程序设计》,其中讲到了javascript中的值传递和值引用,所以就自己研读了一下,但是刚开始没有明白函数中的参数只有值传递,有的场景好像参数是以引用的方式传递的,但是实际上却不是,那到底是怎么回事,或者是函数中的传值是值传递还是值引用呢,下面来对书上给出的例子做一个图解,这样能够更好的解释这个问题。有顿悟的感觉。javascript中貌似共有8种数据类型,包括了字符串类型,数值类型,布尔类型,undefined类型,null类型,对象,数组,函数;
1. 值传递,书上呀,各种的都说基本类型的都是值传递;
基本类型:Number Boolean String Undefined Null 这5种就是javascript种的基本数据类型了;
//基本类型演示:
var a = 1; //数值型
var b = true; //布尔型
var c = undefined; //undefined类型
var d = null; //null类型
var e = 'helloworld'; //字符串类型 var a1 = a; a1 = 2;
console.log(a1); // 2
console.log(a); // 1 var b1 = b;b1 = false;
console.log(b1); //false
console.log(b); //true var c1 = c; c1 = ' ';
console.log(c1); //''
console.log(c); //undefined var d1 = d; d1 = '';
console.log(d1); //''
console.log(d); //null var e1 = e; e1 = 'i love you!';
console.log(e1); //'i love you'
console.log(e); //'helloworld'
上面代码的结果说明了,以上所列几种都是值传递方式的,即原始值不会被改变,原变量与新变量之间在完成赋值,创建原始值的副本之后就没有任何关联了;
2. 值引用,书上呀,各种的都说引用类型的都是值引用;
引用类型:Object Array Fucntion
//1. 对象
var a = {}; var b = a; b.name = '我是b'; console.log(a.name); //'我是b' //2. 数组
var c = []; var d = c; d[0] = '2'; console.log(c); //['2'] //函数
var e = function(){ console.log('我是e函数'); } var f = e; f = function(){ console.log('我是f函数');} console.log(e); functioon(){ console.log('我是f函数');}
新变量中的行为所产生的变化,会同时在原始变量上表现出来,说明原变量在赋值给新变量的时候是将其引用赋值给了新变量,这样他们同时指向同一个引用,这样两个变量中的任何一个的动作所引起的变化都会同时在另一个变量中反应出来。
3. 函数传递参数,书上呀,各种的都说是值传递;
先来简单的看看这个例子:
function setName(obj){
obj.name = 'Nicholas';
}
var person = new Object();
setName(person);
console.log(person.name); //‘Nicholas'
行为:
1. 在内存中创建一个对象,并把这个对象的引用赋值给person变量
2. 将变量person传入函数setName()
3. 函数setName()为obj增加一个name属性,并赋值为’Nicholas‘
4. 访问person的name属性,并将其打印在控制台
在访问person的name属性时,得到的结果是'Nicholas'。但是,这个场景让人感觉好像是值引用;看看下图是程序运行时在内存中的一些变化:

解析:因为函数中的参数是以值传递方式传递的,obj是函数setName()里面的一个局部变量,是在调用函数的时候才发生参数的传递的,调用函数时,person将其拷贝了一份并赋值给了obj,两者是独立的,(因为 person是对象类型的数据,其本质是包含了创建它的对象的引用,在赋值给obj时,赋给obj的也是其原始对象的引用),但是由于两者指向的是同一个引用,所以在为obj添加name属性,并赋值 为“Nicholas”时,操作的不是obj本身的属性,而是操作的其引用Object,而person引用的也是同一个Object,所以在访问person的name属性时,根据javascript 面向对象的原型链规则,首先会检查person 本身是否有name属性,因为person没有name属性,所以继续往上搜索,在其引用的Object上面找到了name属性,所以person.name返回的是其引用的name属性,所以person.name的值是“Nicholas”。
再来看看下面的这个例子
function setName(obj){
obj.name = 'Nicholas';
obj = new Object();
obj.name = 'Grey';
}
var person = new Object();
setName(person);
console.log(person.name); //‘Nicholas'
行为:
1. 在内存中创建一个对象,并把这个对象的引用赋值给person变量
2. 将变量person传入函数setName()
3. 函数setName()为obj增加一个name属性,并赋值为’Nicholas‘
4. 在内存中再新建一个对象,并把这个对象的引用赋值给person变量
5. 为obj增加了一个name属性,并赋值为’Grey‘
4. 访问person的name属性,并将其打印在控制台
解析:上个例子中解释了为什么person.name为’Nicholas‘,这个例子在其基础上添加了两行代码,来看看这两行代码做了什么:
在obj增加了name属性后,又在内存中创建了一个新的Object,而且把它赋值给了obj,根据引用类型的赋值,是把这个新的Object的引用传递给了obj,这点是毫无疑问的。此时obj与原来的对象的引用被新的对象的引用所取代,所以obj实际上与person已经没有任何关系了,此时将obj的name属性值改为“Grey”,其实name属性是不存在的,所以做的不是简单的改变属性的值,而是添加属性,并添加属性值。这个行为与person的引用Object是没有任何关系的,所以person的引用Object中的name也没有发生变化,还是‘Nicholas’。当setName()函数执行完,obj这个局部变量也就不复存在了,但是这对于person来说也是无所谓的。所以当setName()函数执行结束后,访问person的name属性时,如上还是其引用Object的name属性,所以还是‘Nicholas’。
如果按照上例的猜想,函数中的参数是值引用方式,那么我们可以先在脑海里运行一下,会得到什么结果呢?
console.log(person.name) 会在控制台上打印出 ’Grey‘,但是显然结果不是这样的,最终输出的是’Nicholas‘,那是不是我们的猜想错了,函数的参数是值传递方式呢?看看下面的图

所以:基本类型是值传递,引用类型是值引用,函数参数是值传递的说法是完全正确的。
感觉还有点儿细节需要在扣一下,后面在改改。
javascript中值传递与值引用的研究的更多相关文章
- Java 为值传递而不是引用传递
——reference Java is Pass by Value and Not Pass by Reference 其实这个问题是一个非常初级的问题,相关的概念初学者早已掌握,但是时间长了还是容易 ...
- (转载)PHP数组传递是值传递而非引用传递
(转载)http://www.fengfly.com/plus/view-212127-1.html 在调用函数时通过将PHP数组作为实参赋给形参,在函数中修改,并不会影响到数组本身. 说明此过程中的 ...
- 【Qt】信号和槽对值传递参数和引用传递参数的总结
在同一个线程中 当信号和槽都在同一个线程中时,值传递参数和引用传递参数有区别: 值传递会复制对象:(测试时,打印传递前后的地址不同) 引用传递不会复制对象:(测试时,打印传递前后的地址相同) 不在同一 ...
- java是值传递,还是引用传递?
原文地址:http://blog.csdn.net/zxmzfbdc/article/details/5401960 java到底是值传递,还是引用传递?以前国内的java开发者有过很多争论,由于& ...
- JavaScript中对象转换为原始值的规则
JavaScript中对象转换为原始值遵循哪些原则? P52 对象到布尔值对象到布尔值的转换非常简单:所有的对象(包括数字和函数)都转换为true.对于包装对象亦是如此:new Boolean(fal ...
- JavaScript中的方法、方法引用和参数
首先,我们来看一段代码,如果觉得不甚明白的,则本文会对你有益: var player = function (e) { return (function f(m) { ...
- JavaScript中函数参数的值传递和引用传递
结论: 对于数字.字符串等基本类型变量,是将它们的值传递给了函数参数,函数参数的改变不会影响函数外部的变量. 对于数组和对象等是将对象(数组)的变量的值传递给了函数参数,这个变量保存的指向对象(数组) ...
- java方法中只有值传递,没有引用传递
public class Example { String testString = new String("good"); char[] testCharArray = {'a' ...
- 【Java基础】11、java方法中只有值传递,没有引用传递
public class Example { String testString = new String("good"); char[] testCharArray = {'a' ...
随机推荐
- linux进程通信之使用匿名管道进行父子进程通信
管道:是指用于连接一个读进程和一个写进程,以实现它们之间通信的共享文件,又称pipe文件. 管道是单向的.先进先出的.无结构的.固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起 ...
- 使用 Spring 进行单元测试
一.使用spring中对Junit框架的整合功能 除了junit4和spring的jar包,还需要spring-test.jar.引入如下依赖: <dependency> <grou ...
- SAP LOGON DATA CHECK
之前有朋友做过RFC登录验证,后来群里又有很多人问SAP的登录验证函数. 后来自己找找了,看看了,然后改写了一个LOGON DATA CHECK... FUNCTION ZUSER_CHECK_LOG ...
- 20169212《Linux内核原理与分析》 第九周作业
可执行程序的装载 一.预处理.编译.链接和目标文件的格式 可执行程序是怎么来的?通过以下这个图来呈现过程: 以我们常写的helloworld为例.我们编写了一个helloworld的.c文件,我们来把 ...
- 程设大作业xjb写——魔方复原
鸽了那么久总算期中过[爆]去[炸]了...该是时候写写大作业了 [总不能丢给他们不会写的来做吧 一.三阶魔方的几个基本定义 ↑就像这样,可以定义面的称呼:上U下D左L右R前F后B UD之间的叫E,LR ...
- Linux小知识积累
1.Linux图形界面和字符命令行界面的切换 从图形界面切换到字符界面,使用快捷键 Ctrl+Alt+F1 从字符界面切换到图形界面,使用快捷键 Ctrl+Alt+F7 2.解压文件 tar -xzv ...
- 对象列表转换为DataTable或DataTable转换为对象列表.
/**********************************************************************************/ // 说明: 数据转换工具. ...
- office2010密钥
J33GT-XVVYK-VHBBC-VY7FB-MTQ4CGRPWH-7CDHQ-K3G3C-JH2KX-C88H86CCCX-Y93YP-3WQGT-YCKFW-QTTT76QFDX-PYH2G-P ...
- CSS入门
CSS,层叠样式表,是对web页面显示效果进行控制的一套标准.当页面的内容受多种样式控制,将会按照一定的顺序处理.CSS的作用:(1)将网页的内容结构和格式控制分开.(2)可以精确控制页面的所有元素. ...
- 揭秘JavaScript中谜一样的this
揭秘JavaScript中谜一样的this 在这篇文章里我想阐明JavaScript中的this,希望对你理解this的工作机制有一些帮助.作为JavaScript程序员学习this对于你的发展有 ...