• 第一百零五篇:变量的原始值和引用值


    好家伙,JS基础接着学,

    本篇内容为《JS高级程序设计》第四章学习笔记

     

    1.原始值和引用值

    ECMAScript变量可以包含两种不同类型的数据:原始值和引用值。原始值(primitive value)就是最简单的数据,引用值(reference value)则是由多个值构成的对象。

    在把一个值赋给变量时, JavaScript引擎必须确定这个值是原始值还是引用值。

    6种原始值:

    1.Undefined

    2.Null

    3.Boolean

    4.Number

    5.String

    6.Symbol。

    引用值:

    我们常见的引用值就是"对象"

     

    保存原始值的变量是按值(by value )访问的,因为我们操作的就是存储在变量中的实际值。

    (这句是真的抽象,按我的理解来,按值访问即在栈中保存的实际的数值)

     

    引用值是保存在内存中的对象。

    (这句反而好理解,我们可以把他理解为引用值保存的是一个指针,后面的例子会帮助我们更好理解)

     

    与其他语言不同,JavaScript不允许直接访问内存位置(小东西真别致),

    因此也就不能直接操作对象所在的内存空间。

     

    在操作对象时,实际上操作的是对该对象的引用(reference)而非实际的对象本身。

    为此,保存引用值的变量是按引用(by reference)访问的。

     

    注意:在很多语言中,字符串是使用对象表示的,因此被认为是引用类型

     

    2.动态属性

    原始值和引用值的定义方式很类似,都是创建一个变量,然后给它赋一个值。

    不过,在变量保存了这个值之后,可以对这个值做什么,则大有不同。

    2.1.对于原始值,不能添加属性,举个例子

    let panghu_1 = "panghu";
    panghu_1.age
    =20; console.log(panghu_1.age);

    看图:

     

     

     添加属性不会报错,但原始值不能拥有属性

     

    2.2.对于引用值而言,可以随时添加、修改和删除其属性和方法

    let panghu_2 = new String("big panghu");
    panghu_2.age = 20;
    console.log(panghu_2.age);

    看图:

     

     

    来看看两种值的类型判断:

     

    3.复制值

     原始值和引用值在通过变量复制是也有所不同.

    3.1.原始值的复制

    在通过变量把一个原始值赋值到另一个变量时,原始值会被复制到新变量的位置.

    let a = 1;
    let b = a;
    console.log(b);   //1

    (不用上图了吧)

     

    3.2.引用值的复制

    在把引用值从一个变量赋给另一个变量时,存储在变量中的值也会被复制到新变量所在的位置。

    区别在于,这里复制的值实际上是一个指针,它指向存储在堆内存中的对象

    操作完成后,两个变量实际上指向同一个对象,因此一个对象上面的变化会在另一个对象上反映出来,

    (让我们提取重点.复制的值是一个指针,复制后,两个变量指向同一个对象)

    让我们用代码尝试去证明:

    let panghu_1 = new Object();
    let panghu_2 = panghu_1;
    panghu_1.age = 100;
    console.log(panghu_2.age);

    上图:

     

     

     (看,多么神奇的js)

    由此可证明,将panghu_1赋值给panghu_2后,两个变量指向的其实是同一个对象

     

    非常形象的一张图:

     

     

     

    4.传递参数(参数的复制)

    经过我们在上面的一段大发现,我们又产生了新的问题

    4.1.原始值的的参数传递

    复制代码
    function original(a){
        a= a+10;
        return a;
    };
    let b = 10;
    let c = original(b);
    console.log(b);
    console.log(c);
    复制代码

    看图:

     

     这自然是没什么悬念

     

    4.2.初始值的参数传递

    例子4.2.1.

    复制代码
    function Reference(a) {
        a.age = 20;
    };
    let b = new Object();
    Reference(b);
    console.log(b.age);
    复制代码

    上图,

     

    这怎么解释呢? 

    到此为止,有的小伙伴就要说了,

    创建新对象,保存在b中,将b作为参数调用方法Reference();

    此时,b被赋值给了a,此时,a,b指向同一个对象,于是当我a.age=20后,

    b的age属性自然就被设置为"20"了(错误的解释)

    (思路非常清晰,然而这是错的)

     

    我们加两行代码试试:

    例子4.2.2.

    复制代码
    function Reference(a) {
        a.age = 20;
        a = new Object();
        a.age = 1000;
    };
    let b = new Object();
    Reference(b);
    console.log(b.age);
    复制代码
    上图:

     

     (装一下:诶,发生甚么事了,不应该是1000吗)

     

    于是,正确的解释来了:
    我们创建了一个对象并把它保存在变量 b 中。
    然后,这个对象被传给

    Reference()方法,并被复制到参数a中在函数内部,a和b都指向同一个对象结果就是,
    即使对象是按值传进函数的,a也会通过引用访问对象。
    当函数内部给a设置了name属性时,函数外部的对象也会反映这个变化,因为a指向的对象保存在全局作用域的堆内存上。
    这解释了例子4.2.1为什么发生

    那例子4.2.2如何解释呢?
    当a在函数内部被重写时,它变成了一个指向本地对象的指针
    而那个对象在函数执行结束时就被销毁了

    所以我们会知道:Js中所有函数的参数都是按值传递的

     

     

  • 相关阅读:
    【数据结构】单链表 | 详细讲解
    什么样的程序化交易程序才能算好程序?
    金蝶云星空表单插件获取控件值
    win10pycharm和anaconda安装和环境配置教程
    储能直流侧计量表DJSF1352
    老板让你Excel统计数据无从下手?没事,ChatGPT来帮你!
    gRPC入门学习之旅(八)
    微服务注册中心技术选型:5种主流注册中心,哪个最香?
    maven找不到jar包
    雷电模拟器上使用第一个frida(五)用python实现逆向分析并模拟登陆以及两篇好用文章adb devices出现emulator-5554 offline的解决方案和Frida Hook方法大全
  • 原文地址:https://www.cnblogs.com/FatTiger4399/p/16861742.html