js中arr的赋值不影响原数组,赋值和引用的区别

1、赋值

  1. var a = 1;
  2. var b = a;   //赋的是a的复制值
  3. b ++;
  4. alert(a);   //"1"   b的修改不影响a

2、引用

  1. var a = [1];
  2. var b = a;     //赋的是a的引用
  3. b[0] ++;
  4. alert(a);  //"2"   b的修改对a也有效    不过当然b = [2];这种修改对a是没用的。。。。。。

起到引用作用又不影响原数组的方法

方法一:用jq的$.extend方法

  1. <script type="text/javascript">
  2. var a=[1];
  3. var b;
  4. b= $.extend(true,{},a)
  5. b[0]++;
  6. alert(b[0]);
  7. </script>

方法二:用数组的concat方法

  1. <script type="text/javascript">
  2. var a=[1];
  3. var b=a.concat();
  4. b[0]++;
  5. alert(a[0]);
  6. </script>

方法三:用函数传参的方法

      1. 传值的传递:传给函数的是数值的一个复制,函数中对其的修改外部不可见
      2. var a = 1;
      3. var b = 2;
      4. function change(a,b) {
      5. var c = a;
      6. a = b;      //用新引用覆盖
      7. b = c;
      8. alert(a);   //"2"
      9. alert(b);   //"1"
      10. }
      11. change(a,b);
      12. alert(a);   //"1"
      13. alert(b);   //"2"
      14. 传址的传递:传给函数的是数值的一个引用,函数中对其属性的修改外部可见,但用新引用覆盖其则在外部不可见,比如
      15. var a = [1, 2, 3];
      16. var b = [5, 6];
      17. function change(a,b) {
      18. a[0] = 4;    //对其属性的修改外部可见
      19. var c = a;
      20. a = b;      //用新引用覆盖
      21. b = c;
      22. alert(a);   //"5,6"
      23. alert(b);   //"4,2,3"
      24. }
      25. change(a,b);
      26. alert(a);    //"4,2,3"
      27. alert(b);     //"5,6"
      28. 从结果可以看出a和b并没有互换   因为用新引用覆盖在外部不可见 这个很自然 因为函数只是拿到了引用 并没有权力更改引用

JS是按值传递还是按引用传递(object按共享传递)

在分析这个问题之前,我们需了解什么是按值传递(call by value),什么是按引用传递(call by reference)。在计算机科学里,这个部分叫求值策略(Evaluation Strategy)。它决定变量之间、函数调用时实参和形参之间值是如何传递的。
 

按值传递 VS. 按引用传递

按值传递(call by value)是最常用的求值策略:函数的形参是被调用时所传实参的副本。修改形参的值并不会影响实参。
 
按引用传递(call by reference)时,函数的形参接收实参的隐式引用,而不再是副本。这意味着函数形参的值如果被修改,实参也会被修改。同时两者指向相同的值。
 
按引用传递会使函数调用的追踪更加困难,有时也会引起一些微妙的BUG。
 
按值传递由于每次都需要克隆副本,对一些复杂类型,性能较低。两种传值方式都有各自的问题。
 
我们先看一个C的例子来了解按值和引用传递的区别:

复制代码 代码如下:
void Modify(int p, int * q)
{
    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的基本类型,是按值传递的。

复制代码 代码如下:
var a = 1;
function foo(x) {
    x = 2;
}
foo(a);
console.log(a); // 仍为1, 未受x = 2赋值所影响

再来看对象:

复制代码 代码如下:
var obj = {x : 1};
function foo(o) {
    o.x = 3;
}
foo(obj);
console.log(obj.x); // 3, 被修改了!

说明o和obj是同一个对象,o不是obj的副本。所以不是按值传递。 但这样是否说明JS的对象是按引用传递的呢?我们再看下面的例子:

复制代码 代码如下:
var obj = {x : 1};
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的值。

复制代码 代码如下:
var obj = {x : 1};
function foo(o) {
    o = 100;
}
foo(obj);
console.log(obj.x); // 仍然是1, obj并未被修改为100.

然而,虽然引用是副本,引用的对象是相同的。它们共享相同的对象,所以修改形参对象的属性值,也会影响到实参的属性值。

复制代码 代码如下:
var obj = {x : 1};
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值。

复制代码 代码如下:
var str = "abc";
str[0]; // "a"
str[0] = "d";
str; // 仍然是"abc";赋值是无效的。没有任何办法修改字符串的内容

而对象就不一样了,对象是可变的。

复制代码 代码如下:
var obj = {x : 1};
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 参数的 引用与值传递的更多相关文章

  1. vue.js 同级组件之间的值传递方法(uni-app通用)

    vue.js 兄弟组件之间的值传递方法 https://blog.csdn.net/jingtian678/article/details/81634149

  2. 由String作为方法参数,引起的值传递,引用传递,及StringBuffer

    原文引用: http://www.cnblogs.com/zuoxiaolong/p/lang1.html http://www.cnblogs.com/clara/archive/2011/09/1 ...

  3. 论JS函数传参时:值传递与引用传递的区别

    什么是值传递:值传递是指在调用函数时将实际参数(实参)复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数. 值传递的总结:也就是说,将实参复制到函数中的这个过程叫值传递 什么是 ...

  4. js的赋值问题:值传递还是引用传递?

    ECMAScript中有5种简单数据类型(也称为基本数据类型):Undefined.Null.Boolean.Number和String.还有1种复杂数据类型--Object,Object本质上是由一 ...

  5. C#函数的参数传递方式1(值传递与地址传递)

    using System; namespace class1 { class program { static void Main(string[] args) { //值传递引用,实际参数不会变化 ...

  6. js 数组赋值问题 :值传递还是引用?

    转载于知乎var a = [1,2,3]; var b = a; a = [4,5,6]; alert(b); //[1,2,3] 面试时被问到这样一个问题,竟然从来没试过... 当时直接的理解,数组 ...

  7. JS的函数参数传递为值传递

    function setAge(i) { alert(i);//24 i = 18; alert(i);//18,i的改变不会影响外面的age }; var age = 24; setAge(age) ...

  8. 【温故知新C/C++/opencv】取址符&||cv::groupRectangles||引用与值传递

    cv::groupRectangles void groupRectangles(vector<Rect>& rectList, int groupThreshold, doubl ...

  9. 关于PHP参数的引用传递和值传递

    如果希望编写一个名为increment()的函数来增加一个变量的值,我们可能会按如下方式编写这个函数: 这段代码是没有用的.下面测试代码的输出结果是“10”. $value 的内容没有被修改.这要归因 ...

随机推荐

  1. 轻松学习Linux之自动执行任务

    在 Linux 中,任务可以被配置在指定的时间段.指定的日期.或系统平均载量低于指定的数量时自动运行,系统管理员可使用自动化的任务来执行定期备份.监控系统.运行定制脚本等,往往初学者都是win用户,习 ...

  2. php基础知识(1)

    1.判断变量是否存在isset() $v1="a"; if(!isset($v1)){ echo "变量存在"; }else{ echo "变量不存在 ...

  3. EasyUI DataGrid 窗口大小自适用--------------未测试

    EasyUI 新版本里添加了 fit 属性,不需要老版本的那么复杂,重新load DataGrid.但是昨天用的时间发现只有一个DataGrid的时候用fit:true 很好使,但是如果有其它元素,如 ...

  4. 第三百五十四天 how can I 坚持

    你的问题主要在于:读书不多而买书太多:读书太少又特爱思考,还话唠.. 2012年毕业,辗转无锡,上海,最后来到了北京,逛了北京, 2013年,清明去爬了长城,从天通苑搬到了甜水园, 2014年,爬了泰 ...

  5. RFID第二次作业

    1.简述智能卡的发展,以及射频电子标签在其中所处的位置. 智能卡(Smart Card)又称为集成电路卡(IC卡),内部带有微处理器和存储单元等部件. 射频电子标签是一种非接触式的IC卡,是后期发展起 ...

  6. compiled python files

    [compiled python files] As an important speed-up of the start-up time for short programs that use a ...

  7. Unity3D Persistent Storage

    [Unity3D Persistent Storage] 1.PlayerPrefs类以键值对的形式来提供PersistentStorage能力.提供小额存储能力.(做成sst可以提供大规模数据存储) ...

  8. invoking gdb

    [invoking gdb] The most usual way to start gdb is with one argument, specifying an executable progra ...

  9. netdata linux环境下的安装

    据说netdata监控很个性化,采用的显示方式也很漂亮,就来尝试安装.百度搜索到的安装教程的斑斑是1.0.顺藤摸瓜去wiki看了看,已经更新为1.4了,果断走起: 下载地址::https://gith ...

  10. VISIO 2007 修改形状默认字体 自定义模具

    visio 2007的形状的默认字体为8号,比较小,怎样改成默认10号? 首先将一个流程图中所要用的形状都拖到绘图区,然后全选,设置字体为10号,全选,再拖动到形状区,如下图: 点击‘是’,确认修改模 ...