值(value)和引用(reference)是各种编程语言老生常谈的话题,js也不例外。

我将剖析一个例子的实际运行过程,跟大家分享我对js参数传递中的值和引用的理解。

参考官网数据类型的两种分类,本文将这两种分类简称为基本类型(boolean, null, undefined, string, number, symbol)和object类型。

首先,用一个example 演示参数传递的应用:

var obj = {};
obj.inner = 10; var num = 10;
var str = 'Hello';
var boo = true;
var oth = null;
var und = undefined;
var sym = Symbol('foo'); function passingobject(myobj){
myobj.inner = 1 + myobj.inner ;
} function passingvalue(myvalue){
switch(typeof myvalue){
case 'number':
myvalue = myvalue + 1;
break;
case 'string':
myvalue = 'I am a new string now!';
break;
case 'boolean':
myvalue= false;
break;
default:
myvalue = 'Null, Undefined, or Symbol';
}
} console.log("before num = " + num); // before num = 10
passingvalue(num);
console.log("after num = " + num); // after num = 10
console.log("before str = " + str); // before str = Hello
passingvalue(str);
console.log("after str = " + str); // after str = Hello
console.log("before boo = " + boo); // before boo = true
passingvalue(boo);
console.log("after boo = " + boo); // after boo = false
console.log("before oth = " + oth); // before oth = null
passingvalue(oth);
console.log("after oth = " + oth); // after oth = null
console.log("before und = " + und); // before und = undefined
passingvalue(und);
console.log("after und = " + und); // after und = undefined
console.log(sym); // Symbol(foo)
passingvalue(sym);
console.log(sym); // Symbol(foo)
console.log("before obj.inner = " + obj.inner); // before obj.inner = 10
passingobject(obj); // after obj.inner = 11
console.log("after obj.inner = " + obj.inner);

从example 1 的结果似乎可以总结出以下两条结论:

1. 传递的数据类型为基本类型(number, string boolean, null, undefined, symbol),在参数传递过程中,函数内部对传递值的操作并不影响原始值。

2. 传递的数据类型为object, 在参数传递过程中,函数内部对传递值的操作会导致原始值的改变。

然而, 有没有其他特殊情况呢?

有一种在stackoverflow讨论很火热的用法,跟结论二背道而行。example 2。

例子引自:http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language

 function changeStuff(a, b, c)
{
a = a * 10;
b.item = "changed";
c = {item: "changed"};
} var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"}; console.log(obj1.item); // unchanged
console.log(obj2.item); // unchanged
changeStuff(num, obj1, obj2);
console.log(obj1.item); // changed
console.log(obj2.item); // unchanged

example 2中, obj2.item并没有被函数changeStuff改变。changeStuff内部同样改变了b、c的值,为什么obj1被改变了(L15)而obj2没有被改变呢?

我用js的执行上下文对这种现象进行解释,如图。

在js运行过程中,编辑器动态生成执行上下文(execution context),example 2中,首先生成global的执行上下文和changeStuff的执行上下文。

执行到changeStuff(num, obj1, obj2)的时候, a, b, c指向参数num, obj1, obj2,a和num指向10, b跟obj1指向同一个值,c跟obj2指向同一个值。

执行step 1的时候,对a重新赋值,为a赋值前的10倍,从此a与num毫无关系。

执行step 2的时候,对b所指向的值的item属性进行重新赋值,这个赋值只改变了item的值, 而obj1和b仍然指向同一个值。

执行step 3的时候,对c重新赋值,从此c与obj2再无瓜葛,因此即使c有一个叫item的属性,与obj2的item属性有着各自的值,并没有影响obj2.item。

也就是说,js函数参数传递过程中,若函数内部对参数重新赋值,这个赋值过程不会影响原始变量的值。

这也很好地解释了基本类型的参数变量(结论1)不会受影响的现象,基本类型的参数变量每一次改变都是一次全新赋值,对原始变量不会造成影响。

总结

在js函数传递中,当基本类型(number, string, boolean, null, undefined, symbol)变量作为参数传递时,函数内部对参数的任何操作都不会改变变量的值。

当object类型变量作为参数传递时,函数内部对参数的操作会影响变量的值,除非函数内部对参数重新赋值(任何类型的值)。

Thank you!

Feel free to contact me if you have any question!

Javascript参数传递中值和引用的一种理解的更多相关文章

  1. javascript学习中自己对作用域和作用域链理解

    在javascript学习中作用域和作用域链还是相对难理解些,下面我关于javascript作用域和作用域链做一下详细介绍,给各位初学者答疑解惑. 首先我们介绍一下什么是作用域?  从字面上理解就是起 ...

  2. JavaScript检测原始值、引用值、属性

    上周写过一篇读书笔记<编写可维护的JavaScript>之编程实践,其中 第8章 避免『空比较』是博主在工作中遇坑较多的雷区,所以特此把该章节重新整理分享,希望大家不再坑队友(>﹏& ...

  3. javascript参数传递中处理+号

    在传值过程中,如果+号也是值的一部分,那就需要对+号进行处理.否则+号会被过滤掉. 处理方式:只需要把js中传过去的+号替换成base64 编码 %2B encodeURI(str).replace( ...

  4. C#中值和引用

    c#中有两种基本类型,它们分别是值类型和引用类型:而每种类型都可以细分为如下类型: ps:1.基本类型是值类型 2.类.接口.委托都是引用类型

  5. 理解PHP的变量,值与引用的关系

    --- title: 理解PHP的变量,值与引用的关系 createdDate: 2015-03-11 category: php --- PHP的变量与C++中的变量是两种截然不容的概念.如果没有理 ...

  6. opencv-11-中值滤波及自适应中值滤波

    开始之前 在上一篇我们实现了读取噪声图像, 然后 进行三种形式的均值滤波得到结果, 由于我们自己写的均值滤波未作边缘处理, 所以效果有一定的下降, 但是总体来说, 我们得到的结果能够说明我们的算法执行 ...

  7. 基于MATLAB的中值滤波均值滤波以及高斯滤波的实现

    基于MATLAB的中值滤波均值滤波以及高斯滤波的实现 作者:lee神 1.   背景知识 中值滤波法是一种非线性平滑技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值. 中值滤 ...

  8. 中值滤波C语言优化

    中值滤波C语言优化 图像平滑是图像预处理的基本操作,本文首先用不同的方法对一张图片做预处理比较它们效果的不同,然后针对中值滤波,实现了一种快速实现.(其实是copy的opencv实现,呵呵).因为op ...

  9. matlab中fspecial Create predefined 2-D filter以及中值滤波均值滤波以及高斯滤波

    来源: 1.https://ww2.mathworks.cn/help/images/ref/fspecial.html?searchHighlight=fspecial&s_tid=doc_ ...

随机推荐

  1. ndk编译时的通用Android.mk文件

    LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := live555 MY_SRC_PATH := $(LOCAL_PA ...

  2. Uncode-Schedule首页、文档和下载 - 分布式任务调度组件 - 开源中国社区

    Uncode-Schedule首页.文档和下载 - 分布式任务调度组件 - 开源中国社区 分布式任务调度组件 Uncode-Schedule

  3. 20个 Unix/Linux 命令技巧

    让我们用这些Unix/Linux命令技巧开启新的一年,提高在终端下的生产力.我已经找了很久了,现在就与你们分享. 删除一个大文件 我在生产服务器上有一个很大的200GB的日志文件需要删除.我的rm和l ...

  4. 【Lucene3.6.2入门系列】第14节_SolrJ操作索引和搜索文档以及整合中文分词

    package com.jadyer.solrj; import java.util.ArrayList; import java.util.List; import org.apache.solr. ...

  5. Jquery案例——某网站品牌列表的效果

    一下是效果图.点击"显示全部品牌",高亮推荐品牌,并显示全部品牌. HTML文件: <!DOCTYPE html> <html lang="en&quo ...

  6. mysql常用总结

    用户管理mysql>use mysql;查看mysql> select host,user,password from user ;创建mysql> create user zx_r ...

  7. editplus 使用小技巧

    1 editplus怎么设置tab键跳的字符数? Tools -> Preferences -> Files -> Settings & syntax -> Tab/I ...

  8. DataTable无法使用AsEnumerable ()的解决办法

    本人定义了DataSet后将表1赋给datatable,在写linq时调用datatable.asenumerable(),但报datatable不包含asenumerable的定义,求高手指点.Sy ...

  9. 经常使用虚拟现实仿真软件总汇(zz)

     经常使用虚拟现实仿真软件总汇(zz)http://hi.baidu.com/busycai/blog/item/fe57e41e5f25fa1c403417b2.html 2007年09月07日 星 ...

  10. Delphi下实现全屏快速找图找色

    前言 最近有好几个朋友都在问我找图找色的问题,奇怪?于是乎写了一个专门用于找图找色的单元文件“BitmapData.pas”.在这个单元文件中我实现了从文件中导入位图.屏幕截图.鼠标指针截图.在图片上 ...