值和引用

function foo(x) {
    x.push(4);
    console.log(x); //1,2,3,4
    x = [4, 5, 6];
    x.push(7);
    console.log(x);//4,5,6,7
}
var a = [1, 2, 3];
foo(a);
console.log(a);//1,2,3,4

在传递a的时候,其实是将引用a的一个复本赋值给x,而a仍然指向x,在方法中,我们可以通过x来改变数组的值,然后重新赋值x=[4,5,6],但这病不影响a的指向
所以我们不能通过引用x来更改引用a的指向,只能更改a和x共同指向的值
如果要改变原值,就必须改变x指向的数组,而不是为x赋值一个新的数组,例如:

function foo(x) {
    x.push(4);
    console.log(x); //1,2,3,4
    x.length = 0;
    x.push(4, 5, 6,7);
    console.log(x);//4,5,6,7
}

请记住,我们无法自行决定使用值复制还是引用复制,一切由值的类型来确定。
如果通过值复制的方式来传递复合数组,就需要为其创建一个复本,例如:

foo(a.slice());

相反如果要将基本类型的值传递到函数中并进行更改,就需要将值封装到一个复合对象中,然后进行传递。

function foo(o) {
    o.a = 11;
}
var obj = {
    a:2
}
foo(obj);
console.log(obj.a);

在看下基本类型对象传递时的问题:

 function foo(x) {
            x = x + 1;
            console.log(x);
        }

        var a = 2;
        var b = new Number(a);//object(a)也一样
        foo(b);
        console.log(b);//2

上面虽然传递的是对象的引用,但是也并未更改函数外部的值,原因是标量的基本类型值是不可以更改的(字符串和布尔也是如此),如果一个数字对象的标量基本类型值是2,那么该值就不能更改,
除非创建一个包含新值的数字对象。
x=x+1中,x中的标量基本类型值2从数组对象中拆封出来后,x就神不知鬼不觉的从引用变成了数字对象,他的值为3,然而函数外的b仍然指向原来的那个值为2的对象。

时间: 2024-09-30 16:34:27

值和引用的相关文章

【我的OOP学习笔记】值与引用(2)语义类型

值与引用 值语义的对象是独立的,语义的对象却是允许共享的.由于Java不支持值类型对象,Java程序员才更需要加强这方面的意识.语法和语义并不总是一致的——语法上的值类型可能在语义上是引用类型,语法上的引用类型可能在语义上是值类型.永远不要忘记一个基本原则:语法只是手段,语义才是目的. 为了判断一个类型的语义,那么简明的‘石蕊测试法’便是一个很好的选择.在不影响程序正确性的前提下,一个对象的复件能否代替原件?如果可以则该对象的类型是值语义的,否则是引用语义的.(这种判断方法与语法无关,完全取决于

C# 函数参数传递(按值和引用)

C#中的数据类型.分值类型和引用类型两大类. 值类型:直接存储数据的值,保存在内存中的stack(堆栈)中 引用类型:存储对值的引用,实际上存储的就是一个内存的地址.引用类型的保存分成两块,实际值保存在托管堆(heap)中.实际值的内存地址保存在stack中 当使用引用类型时先找到stack中的地址,再找到heap中的实际值. 也就是说保存引用类型时要用到stack和heap,但使用引用类型时我们实际上只用到stack中的值,然后通过这个值间接的访问heap中的值 C#预定义的简单类型,像int

ECMAScript 原始值和引用值

在 ECMAScript 中,变量可以存在两种类型的值,即原始值和引用值. 原始值和引用值 在 ECMAScript 中,变量可以存在两种类型的值,即原始值和引用值. 原始值 存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置. 引用值 存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存处. 为变量赋值时,ECMAScript 的解释程序必须判断该值是原始类型,还是引用类型.要实现这一点,解释程序则需尝试判断该值是否

为什么赋值操作符函数的参数为const引用,返回值为引用

为什么赋值操作符函数的参数为const引用,返回值为引用 1.返回值类型 返回类型一般声明为类型的引用,并在函数结尾时返回实例自身的引用(即*this).这里主要有两个原因:(1)返回引用可以减少一次拷贝构造和析构函数导致不必要的开销,因为返回值类型不是引用,会创建一个匿名对象,这个匿名对象时个右值,获取return的值.(2)可以实现连续赋值 在例子中 b=c=a; 返回值不是引用类型也是可以的,其运算顺序 b=(c=a); c得到一个右值,再将右值赋给b,所以逻辑上没有问题的.但是如果是 (

js中 原始值和引用值

在 ECMAScript 中,变量可以存在两种类型的值,即原始值和引用值. 原始值-----存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置; 引用值-----存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存处. 如果一个值是引用类型的,那么它的存储空间将从堆中分配.由于引用值的大小会改变,所以不能把它放在栈中,否则 会降低变量查寻的速度.相反,放在变量的栈空间中的值是该对象存储在堆中的地址.地址的大小是固定的,

js 值和引用

js对值和引用的赋值/传递在语法上没有区别,完全根据值得类型决定 简单值(即标量基本类型值),总是通过值复制的方式来赋值/传递,包括null,undefined,字符串,数字,布尔值和ES6中的symbol. 复合值--对象(包括数组和封装对象)和函数,则总是通过引用复制的方式来赋值/传递. __________________________________ 简单值 var a0=2;var b0=a0;b0++;console.log(a0);//2console.log(b0);//3 简

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

--- title: 理解PHP的变量,值与引用的关系 createdDate: 2015-03-11 category: php --- PHP的变量与C++中的变量是两种截然不容的概念.如果没有理解清楚,使用C++的方式来思考PHP就会遇到一些问题. C++中,变量与值是绑定的.值是内存的上的一块内存上的数据,而变量则是操作这块内存的名称.变量消失(比如超出作用域)值也会消失. 而PHP中,变量和值是两个概念.PHP是一种弱类型语言,值在PHP的内部(zend引擎),被存放在一个zval结构

原始值和引用值

在 ECMAScript 中,变量可以存在两种类型的值,即原始值和引用值. 原始值 存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置. 引用值 存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存处. 为变量赋值时,ECMAScript 的解释程序必须判断该值是原始类型,还是引用类型.要实现这一点,解释程序则需尝试判断该值是否为 ECMAScript 的原始类型之一,即 Undefined.Null.Boolean.

JavaScript-原始值和引用值

一.原始值和引用值的概念 在 ECMAScript 中,变量可以存在两种类型的值,即原始值和引用值. 1.1 原始值 (1)原始值指的是 原始类型 的值,也叫 基本类型,例如 Number.Stirng.Boolean.Null.Underfined . (2)存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置. (3)注意 在许多语言中,字符串都被看作引用类型,而非原始类型,因为字符串的长度是可变的.ECMAScript 打破了这一传统. 1.2 引用值 (1)引

值传递 引用传递

方法参数传递有2种方式: 值传递和引用传递. 值传递: 默认都是值传递.值传递有2种,值类型和引用类型的.实质是复制栈中的值. 值类型的值传递:栈中的值就是实际值. 引用类型的值传递:栈中的值是内存堆中地址. 引用传递: 参数前加ref的为引用传递,引用传递有2种,值类型和引用类型的.实质就是传递自己本身,只是多了个别名.