js 参数的 引用与值传递
js中arr的赋值不影响原数组,赋值和引用的区别
1、赋值
- var a = 1;
- var b = a; //赋的是a的复制值
- b ++;
- alert(a); //"1" b的修改不影响a
2、引用
- var a = [1];
- var b = a; //赋的是a的引用
- b[0] ++;
- alert(a); //"2" b的修改对a也有效 不过当然b = [2];这种修改对a是没用的。。。。。。
起到引用作用又不影响原数组的方法
方法一:用jq的$.extend方法
- <script type="text/javascript">
- var a=[1];
- var b;
- b= $.extend(true,{},a)
- b[0]++;
- alert(b[0]);
- </script>
方法二:用数组的concat方法
- <script type="text/javascript">
- var a=[1];
- var b=a.concat();
- b[0]++;
- alert(a[0]);
- </script>
方法三:用函数传参的方法
- 传值的传递:传给函数的是数值的一个复制,函数中对其的修改外部不可见
- var a = 1;
- var b = 2;
- function change(a,b) {
- var c = a;
- a = b; //用新引用覆盖
- b = c;
- alert(a); //"2"
- alert(b); //"1"
- }
- change(a,b);
- alert(a); //"1"
- alert(b); //"2"
- 传址的传递:传给函数的是数值的一个引用,函数中对其属性的修改外部可见,但用新引用覆盖其则在外部不可见,比如
- var a = [1, 2, 3];
- var b = [5, 6];
- function change(a,b) {
- a[0] = 4; //对其属性的修改外部可见
- var c = a;
- a = b; //用新引用覆盖
- b = c;
- alert(a); //"5,6"
- alert(b); //"4,2,3"
- }
- change(a,b);
- alert(a); //"4,2,3"
- alert(b); //"5,6"
- 从结果可以看出a和b并没有互换 因为用新引用覆盖在外部不可见 这个很自然 因为函数只是拿到了引用 并没有权力更改引用
JS是按值传递还是按引用传递(object按共享传递)
按值传递 VS. 按引用传递
按值传递(call by value)是最常用的求值策略:函数的形参是被调用时所传实参的副本。修改形参的值并不会影响实参。
按引用传递(call by reference)时,函数的形参接收实参的隐式引用,而不再是副本。这意味着函数形参的值如果被修改,实参也会被修改。同时两者指向相同的值。
按引用传递会使函数调用的追踪更加困难,有时也会引起一些微妙的BUG。
按值传递由于每次都需要克隆副本,对一些复杂类型,性能较低。两种传值方式都有各自的问题。
我们先看一个C的例子来了解按值和引用传递的区别:
{
p = 27; // 按值传递 - p是实参a的副本, 只有p被修改
*q = 27; // q是b的引用,q和b都被修改
}
int main()
{
int a = 1;
int b = 1;
Modify(a, &b); // a 按值传递, b 按引用传递,
// a 未变化, b 改变了
return(0);
}
这里我们可以看到:
a => p按值传递时,修改形参p的值并不影响实参a,p只是a的副本。
b => q是按引用传递,修改形参q的值时也影响到了实参b的值。
探究JS值的传递方式
JS的基本类型,是按值传递的。
function foo(x) {
x = 2;
}
foo(a);
console.log(a); // 仍为1, 未受x = 2赋值所影响
再来看对象:
function foo(o) {
o.x = 3;
}
foo(obj);
console.log(obj.x); // 3, 被修改了!
说明o和obj是同一个对象,o不是obj的副本。所以不是按值传递。 但这样是否说明JS的对象是按引用传递的呢?我们再看下面的例子:
function foo(o) {
o = 100;
}
foo(obj);
console.log(obj.x); // 仍然是1, obj并未被修改为100.
如果是按引用传递,修改形参o的值,应该影响到实参才对。但这里修改o的值并未影响obj。 因此JS中的对象并不是按引用传递。那么究竟对象的值在JS中如何传递的呢?
按共享传递 call by sharing
准确的说,JS中的基本类型按值传递,对象类型按共享传递的(call by sharing,也叫按对象传递、按对象共享传递)。最早由Barbara
Liskov. 在1974年的GLU语言中提出。该求值策略被用于Python、Java、Ruby、JS等多种语言。
该策略的重点是:调用函数传参时,函数接受对象实参引用的副本(既不是按值传递的对象副本,也不是按引用传递的隐式引用)。 它和按引用传递的不同在于:在共享传递中对函数形参的赋值,不会影响实参的值。如下面例子中,不可以通过修改形参o的值,来修改obj的值。
function foo(o) {
o = 100;
}
foo(obj);
console.log(obj.x); // 仍然是1, obj并未被修改为100.
然而,虽然引用是副本,引用的对象是相同的。它们共享相同的对象,所以修改形参对象的属性值,也会影响到实参的属性值。
function foo(o) {
o.x = 3;
}
foo(obj);
console.log(obj.x); // 3, 被修改了!
对于对象类型,由于对象是可变(mutable)的,修改对象本身会影响到共享这个对象的引用和引用副本。而对于基本类型,由于它们都是不可变的
(immutable),按共享传递与按值传递(call by value)没有任何区别,所以说JS基本类型既符合按值传递,也符合按共享传递。
var a = 1; // 1是number类型,不可变 var b = a; b = 6;
据按共享传递的求值策略,a和b是两个不同的引用(b是a的引用副本),但引用相同的值。由于这里的基本类型数字1不可变,所以这里说按值传递、按共享传递没有任何区别。
基本类型的不可变(immutable)性质
基本类型是不可变的(immutable),只有对象是可变的(mutable). 例如数字值100, 布尔值true,
false,修改这些值(例如把1变成3,
把true变成100)并没有什么意义。比较容易误解的,是JS中的string。有时我们会尝试“改变”字符串的内容,但在JS中,任何看似对
string值的”修改”操作,实际都是创建新的string值。
str[0]; // "a"
str[0] = "d";
str; // 仍然是"abc";赋值是无效的。没有任何办法修改字符串的内容
而对象就不一样了,对象是可变的。
obj.x = 100;
var o = obj;
o.x = 1;
obj.x; // 1, 被修改
o = true;
obj.x; // 1, 不会因o = true改变
这里定义变量obj,值是object,然后设置obj.x属性的值为100。而后定义另一个变量o,值仍然是这个object对象,此时obj和
o两个变量的值指向同一个对象(共享同一个对象的引用)。所以修改对象的内容,对obj和o都有影响。但对象并非按引用传递,通过o =
true修改了o的值,不会影响obj。
js 参数的 引用与值传递的更多相关文章
- vue.js 同级组件之间的值传递方法(uni-app通用)
vue.js 兄弟组件之间的值传递方法 https://blog.csdn.net/jingtian678/article/details/81634149
- 由String作为方法参数,引起的值传递,引用传递,及StringBuffer
原文引用: http://www.cnblogs.com/zuoxiaolong/p/lang1.html http://www.cnblogs.com/clara/archive/2011/09/1 ...
- 论JS函数传参时:值传递与引用传递的区别
什么是值传递:值传递是指在调用函数时将实际参数(实参)复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数. 值传递的总结:也就是说,将实参复制到函数中的这个过程叫值传递 什么是 ...
- js的赋值问题:值传递还是引用传递?
ECMAScript中有5种简单数据类型(也称为基本数据类型):Undefined.Null.Boolean.Number和String.还有1种复杂数据类型--Object,Object本质上是由一 ...
- C#函数的参数传递方式1(值传递与地址传递)
using System; namespace class1 { class program { static void Main(string[] args) { //值传递引用,实际参数不会变化 ...
- js 数组赋值问题 :值传递还是引用?
转载于知乎var a = [1,2,3]; var b = a; a = [4,5,6]; alert(b); //[1,2,3] 面试时被问到这样一个问题,竟然从来没试过... 当时直接的理解,数组 ...
- JS的函数参数传递为值传递
function setAge(i) { alert(i);//24 i = 18; alert(i);//18,i的改变不会影响外面的age }; var age = 24; setAge(age) ...
- 【温故知新C/C++/opencv】取址符&||cv::groupRectangles||引用与值传递
cv::groupRectangles void groupRectangles(vector<Rect>& rectList, int groupThreshold, doubl ...
- 关于PHP参数的引用传递和值传递
如果希望编写一个名为increment()的函数来增加一个变量的值,我们可能会按如下方式编写这个函数: 这段代码是没有用的.下面测试代码的输出结果是“10”. $value 的内容没有被修改.这要归因 ...
随机推荐
- Compiling Xen-4.4 From Source And Installing It On Ubuntu Server (Amd-64)
First of all, you should install a clean Ubuntu Server (Amd-64) on your server. (Version 14.04 is st ...
- CSStickyHeaderFlowLayout collectionView headerView 悬浮
github:https://github.com/levyleo/CSStickyHeaderFlowLayout iOS 10 使用时会出现崩溃:https://github.com/CSStic ...
- 全面理解Linux输入输出重定向
全面理解Linux输入输出重定向 本教程通过视频方式讲解shell操作,理解感念,教程通俗易懂,比起看一大堆文档要舒服的多.本次教程主要讲解 Linux Shell 中支持输入输出重定向,用符号&l ...
- Ubuntu14.04上安装pip的方法
在Ubuntu14.04上,建议通过下面的方法安装,这是一种通用的方法,也适用于Windows,当然在Windows下 手动下载下来就行了 wget https://bootstrap.pypa.io ...
- cocos2d-x 3.2 例子文件工程的位置
更新到3.2后突然想要看看官方的例子,忽然发现在test中的cpp工程下面没有了工程的启动配置.奇怪,难道只有代码吗?重新查找后原来启动的工程文件都移动到了build文件夹下面,具体的路径就是 coc ...
- jspace2d——A free 2d multiplayer space shooter
http://code.google.com/p/jspace2d/ —————————————————————————————————————————————————————————————— We ...
- Speex for Android
http://blog.csdn.net/chenfeng0104/article/details/7088138在Android开发中,需要录音并发送到对方设备上.这时问题来了,手机常会是GPRS. ...
- NLP初步
[NLP初步] NLP是Natural Lanuage Process的缩写.搜索引擎可以通过关词匹配和完成很多的任务, 比如话题搜索(搜索包含律师, 法院, 控告等词的文档), 但是搜索引擎无法理解 ...
- oracle学习 四(持续更新中)无法为表空间 MAXDATA 中的段创建 INITIAL 区
解决建立表的时候出现的 ORA-01658: 无法为表空间 MAXDATA 中的段创建 INITIAL 区 出现这个问题是因为表空间的大小不足,可以给他扩容这样的话也会多出来一个数据文件.具体写法如下 ...
- F5 负载均衡 相关资源
F5负载均衡之检查命令的说明http://net.zdnet.com.cn/network_security_zone/2010/0505/1730942.shtml F5培训http://wenku ...