JavaScript数据操作_浅谈原始值和引用值的操作本质

我的一句话总结:原始值不管是变量赋值还是函数传递都不会改变原值,引用值不管是变量赋值还是函数传递,如果新变量重新赋值,则不会影响原引用值,如新变量是直接操作,就会影响原引用值。

首先明确,值和类型是两个不同的概念。例如,null是null类型的唯一值、undefined是undefined类型的唯一值、而true和false是boolean类型仅有的两个值等。在任何语言中,值的操作都可以归纳为以下3个方面。

复制值:即把值赋值给新变量,或者通过变量把值赋值给另一个变量、属性或数组元素。

传递值:即把值作为参数传递给函数或方法。

比较值:即把值与另一个值进行比较,看是否相等。

由于值类型数据和引用型数据的值存在形式不同,自然操作它们的方法和所产生的结果也是不同的。注意,当值为值类型数据时,我们常称之为原始值或基本值;当值为引用型数据时,我们常称之为引用值或复合值。

1.使用原始值

对于原始值来说,其操作的3个层面说明如下。

1)复制值

在赋值语句中,操作的过程将会产生一个实际值的副本,副本的值和实际值之间没有任何联系,它们独自位于不同的栈区或者堆区。这个副本可以存储变量、对象的属性和数组的元素。例如:

var n = 123, a, b = [], c = {};
a = n;         // 复制数字123
b[0] = n;        // 复制数字123
c.x = n;        // 复制数字123
(a == b[0]) && (a == c.x) && (b[0] == c.x) && alert("复制的值都是相等的");  // 检测它们的值都是相等的 

在上面示例中,分别把值123复制3份给变量a、数组b和对象c,虽然它们的值是相等的,但是它们之间是相互独立的。

2)传递值

当把值传递给函数或方法时,传递的值仅是副本,而不是值本身。例如,如果在函数中修改传递进来的值时,结果只能够影响这个参数值的副本,并不会影响到原来的值。

var a = 123;    // 原来的值 

function f(x){
  x = x + x;
}
f(a);      // 调用函数修改传递的值 

alert(a);   // 查看变量a的值是否受影响,返回值为123,说明没有变化

3)比较值

在上面的示例中我们也可以看到,当对原始值进行比较时,进行逐字节的比较来判断它们是否相等。比较的是值本身,而不是值所处的位置,固然比较的结果可能会相等,但只是说明它们所包含的字节信息是相同的。

2.使用引用值

对于引用值来说,其操作的3个层面说明如下。

1)复制值

在赋值语句中,所赋的值是对原值的引用,而不是原值副本,更不是原值本身。也就是说,进行赋值之后,变量保存的都是对原值的引用(即原值的存储地址)。当在多个变量、数组元素或对象属性中间复制时,它们都会与原始变量保存的引用相同。

所有引用具有相同的效力和功能,都可以执行操作,如果通过其中的一个引用编辑数据,这种修改将会在原值及其他相关引用中体现出来。例如:

var a = [1,2,3];  // 赋值数组引用
b = a;         // 复制值
b[0] = 4;      // 修改变量b中第一个元素的值
alert(a[0]);     // 返回4,显示变量a中第一个元素的值也被修改为4 

但是,如果给变量b重新赋予新值,则新值不会影响原值内容。例如:

var a = [1,2,3];  // 赋值数组引用
b = a;         // 复制值
b = 4;         // 为变量b重写赋值
alert(a[0]);     // 变量a的内容保持不变 

重复赋值实际上是覆盖变量对原值的引用,变为另一个值的副本或对其引用。所以不会对原值产生影响,演示示意图如图4-2所示。

  

2)传递值

当使用引用将数据传递给函数时,传递给函数的也是对原值的一个引用,函数可以使用这个引用来修改原值本身,任何修改在函数外部都是可见的。例如:

var a = [1,2,3];
function f(x){
  x[0] = 4;   // 在函数中修改参数值
}
f(a);       // 传递引用值
alert(a[0]);    // 返回4,原值发生变化 

请注意,在函数内修改的是对外部对象或数组的引用,而不是对象或数组本身的值。在函数内可以使用引用来修改对象的属性或数组的元素,但是如果在函数内部使用一个新的引用覆盖原来的引用,那么在函数内部的修改就不会影响原引用的值,函数外部也是看不到的。

var a = [1,2,3];
function f(x){
  x = 4;    // 在函数中修改参数值
}
f(a);       // 传递引用值
alert(a[0]);    // 返回1,原值不会发生变化 

3)比较值

当比较两个引用值时,比较的是两个引用地址,看它们引用的原值是否为同一个副本,而不是比较它们的原值字节是否相等。当对两个不同值进行引用时,尽管它们具有相同的字节构成,但是这两个引用的值却是不相等的。

var a = new Number(1);  // 引用值a
var b = new Number(1);  // 引用值b
var c = a;        // 把a的引用赋值给c
alert(a==b);       // 返回false
alert(a==c);       // 返回true 

所以,{} == {},[] == [],都返回false。因为引用地址不同。

总之,对于任何语言来说,使用值和使用引用都是数据操作的两种基本方法。当我们操作数据时,要采用什么方法来进行处理,主要看数据的类型。值类型和引用型数据参与运算的方式不同,值类型数据通过使用值来操作数据,而引用型数据使用引用来操作数据。运算方式的不同,自然所产生的结果也不同。我们不妨再看一个示例:

var s = "abc";         // 字符串,值类型数据
var o = new String(s);     // 字符串对象,被装箱后的字符串 

function f(v){         // 运算函数
  v.toString = function(){  // 修改参数的方法toString()
    return 123;
  };
} 

f(s);    // 传入值
alert(s);  // 返回字符串"abc",说明运算没有对原数据造成影响
f(o);    // 传入引用
alert(o);  // 返回数值123,说明运算已经影响到原数据的内部结构

值类型是以实际值参与运算的,因此与原数据没有直接联系。而引用型以引用地址参与运算,计算的结果会影响到引用地址所关联的堆区数据块。但是,有一点例外,对于JavaScript的字符串来说,它的操作方法就比较复杂,详情请google!

以上这篇JavaScript数据操作_浅谈原始值和引用值的操作本质就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • JavaScript基本数据类型及值类型和引用类型

    在JavaScript中四种基本的数据类型:数值(整数和实数).字符串型(用""号或''括起来的字符或数值).布尔型(使True或False表示)和空值.在JavaScript的基本类型中的数据可以是常量,也可以变量.由于JavaScript采用弱类型的形式,因而一个数据的变量或常量不必首先作声明,而是在使用或赋值时确定其数据的类型的.当然也可以先声明该数据的类型,它是通过在赋值时自动说明其数据类型的. javascript中的变量 javascript中的变量只是一个占位符,前言已经

  • JavaScript检测原始值、引用值、属性

    在 JavaScript 中,我们常常会看到这样的代码:变量与 null 的比较(这种用法很有问题),用来判断变量是否被赋予了一个合理的值.比如: var Controller = { process: function(items) { if (items !== null) { // 不好的写法 items.sort(); items.forEach(function(item) { // 执行一些逻辑 }); } } } 在这段代码中, process() 方法显然希望 items 是一个

  • JavaScript数据类型之基本类型和引用类型的值

    ECMAScript变量包含两种不同数据类型的值:基本类型值和引用类型值.基本类型值是简单的数据段,而引用类型值指那些可能由多个值构成的对象. 在将一个值赋给变量时,解析器必须确定这个值是基本类型还是引用类型.基本类型包括如Undefined.Null.Boolean.Number和String,这5种基本类型数据类型是按值访问的,因此可以操作保存在变量中的实际的值:引用类型类型的值是保存在内存中的对象.与其他语言不同,JavaScript不允许直接访问内存中的位置,也就是说不能直接操作对象的内

  • JavaScript中值类型与引用类型实例说明

    复制代码 代码如下: <script type="text/javascript"> var str = 'abced'; var obj = new String(str); function newToString() { return 'hello,world'; } function func(val) { val.toString = newToString; } func(str); //ps:实际只传入了str的值,因此对它的toString修改是无意义的 传

  • JavaScript数据操作_浅谈原始值和引用值的操作本质

    我的一句话总结:原始值不管是变量赋值还是函数传递都不会改变原值,引用值不管是变量赋值还是函数传递,如果新变量重新赋值,则不会影响原引用值,如新变量是直接操作,就会影响原引用值. 首先明确,值和类型是两个不同的概念.例如,null是null类型的唯一值.undefined是undefined类型的唯一值.而true和false是boolean类型仅有的两个值等.在任何语言中,值的操作都可以归纳为以下3个方面. 复制值:即把值赋值给新变量,或者通过变量把值赋值给另一个变量.属性或数组元素. 传递值:

  • javascript学习笔记_浅谈基础语法,类型,变量

    基础语法.类型.变量 非数字值的判断方法:(因为Infinity和NaN他们不等于任何值,包括自身) 1.用x != x ,当x为NaN时才返回true; 2.用isNaN(x) ,当x为NaN或非数字值时,返回true; 3.用isFinity(x),在x不是NaN.Infinity.-Infinity时返回true; 虽然(字符串.数字.布尔值)不是对象,他们的属性是只读的,但也可以像操作对象一样来引用他们的属性和方法,原理: javascript构造一个(String.Number.Boo

  • JS中原始值和引用值的储存方式示例详解

    在ECMAscript中,变量可以存放两种类型的值,即原始值和引用值 原始值指的是代表原始数据类型的值,也叫基本数据类型,包括:Number.Stirng.Boolean.Null.Underfined 引用值指的是复合数据类型的值,包括:Object.Function.Array.Date.RegExp 根据数据类型不同,有的变量储存在栈中,有的储存在堆中.具体区别如下: 原始变量及他们的值储存在栈中,当把一个原始变量传递给另一个原始变量时,是把一个栈房间的东西复制到另一个栈房间,且这两个原始

  • Python入门_浅谈数据结构的4种基本类型

    数据结构:通俗点说,就是储存大量数据的容器.这里主要介绍Python的4种基本数据结构:列表.字典.元组.集合. 格式如下: 列表:list = [val1,val2,val3,val4],用中括号: 字典:dict = {key1:val1,key2:val2},大括号,且每个元素是带有冒号的key与val的对应关系组: 元组:tuple = (val1,val2,val3,val4),小括号: 集合:set = {val1,val2,val3,val4},大括号. 1. 列表: list =

  • Python入门_浅谈for循环、while循环

    Python中有两种循环,分别为:for循环和while循环. 1. for循环 for循环可以用来遍历某一对象(遍历:通俗点说,就是把这个循环中的第一个元素到最后一个元素依次访问一次).for循环的基本结构如下: 具体看这个案例: 设计一个函数,在桌面创建10个文本,用数字从1-10依次给它们命名. def text_create(): path = '/Users/duwangdan/Desktop/' for text_name in range(1,11): # 1-10的范围需要用到r

  • python进阶_浅谈面向对象进阶

    学了面向对象三大特性继承,多态,封装.今天我们看看面向对象的一些进阶内容,反射和一些类的内置函数. 一.isinstance和issubclass class Foo: pass class Son(Foo): pass s = Son() #判断一个对象是不是这个类的对象,传两个参数(对象,类) print(isinstance(s,Son)) print(isinstance(s,Foo)) #type更精准 print(type(s) is Son) print(type(s) is Fo

  • 浅谈Python数据类型判断及列表脚本操作

    数据类型判断 在python(版本3.0以上)使用变量,并进行值比较时.有时候会出现以下错误: TypeError: unorderable types: NoneType() < int() 或者类似的类型错误. 这是因为一方变量的数据类型不明(python无法判断),所以出错. 在一般情况下,可以提前对要使用的变量进行定义并赋值,例如: var=' ' 或者 var=0 等等. 但是,若变量在比较前,是通过调用函数或者其他表达式赋值的,以上方法可能行不通,因为如果调用的函数如果存在错误或者没

  • Python入门_浅谈逻辑判断与运算符

    这是关于Python的第6篇文章,主要介绍下逻辑判断与运算符. (一) 逻辑判断: 如果要实现一个复杂的功能程序,逻辑判断必不可少.逻辑判断的最基本标准:布尔类型. 布尔类型只有两个值:True和False,在Python语言中对应的是1和0. 在Pycharm中输入如下代码,运行后将会得到True或False的反馈. print(1 > 2) print('m' in 'member') print(7 >= 7) print(3 != 3) 在这里,我们将能返回布尔值的表达式称为布尔表达式

  • 浅谈mysql_query()函数的返回值问题

    问题描述: 我在操作mysql,插入数据时,关闭资源,PHP提示了一个warning.内容大致为,需要给mysql_free_result()一个资源类型. 然后,我将返回的结果var_dump($res),发现是bool值 分析: 看手册时,一眼看上去,觉得mysql_query()函数返回的本来就是资源类型,可是为什么现在又是bool值了呢?好吧,耐心看完手册,才发现,原理是这样的,如下图片: 总结:由上可以知道,mysql_query()执行sql语句时,并不是什么时候都要执行释放结果集,

  • 浅谈DataFrame和SparkSql取值误区

    1.DataFrame返回的不是对象. 2.DataFrame查出来的数据返回的是一个dataframe数据集. 3.DataFrame只有遇见Action的算子才能执行 4.SparkSql查出来的数据返回的是一个dataframe数据集. 原始数据 scala> val parquetDF = sqlContext.read.parquet("hdfs://hadoop14:9000/yuhui/parquet/part-r-00004.gz.parquet") df: or

随机推荐