zoukankan      html  css  js  c++  java
  • javascript中所有函数参数都是按值传递

    在看《JavaScript高级程序设计》(第三版)的时候,传递参数这一节,里面提到

    ECMAScript中所有函数的参数都是按值传递的

    它自己的解释是,

    把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。
    基本类型值的传递如同基本类型变量的复制一样,
    而引用类型值的传递,则如同引用类型变量的复制一样。

    我们先明白几个概念,之后再讨论。

    数据类型

    基本数据类型,有6种,Undefined、Null、Boolean、Number、String、Symbol

    引用类型,Object、Array、Date、RegExg、Function等

    数据类型介绍,可以参考JavaScript数据类型的非常6+1

    内存空间

    var a = 2
    var b = 'abc'
    var c = true
    var d = {value : 1}
    var e = [1, 2, 3]
    

    定义的以上几个变量,在内存中,所占用的空间如图示意:

    内存空间示意图

    基础数据类型值,在栈中存储实际的值。引用数据类型值,在栈中存储引用地址值,在堆中存储实际的值。

    赋值拷贝/复制

    基础数据类型,赋值拷贝,拷贝实际值

    
    var a = 1
    
    var b = a
    
    b = 2
    
    console.log(a) // 1
    
    

    引用类型,赋值拷贝,拷贝引用地址,浅拷贝。可以参考javascript中的浅拷贝ShallowCopy与深拷贝DeepCopy

    
    var a = {value : 1}
    
    var b = a
    
    b.value = 2
    
    console.log(a.value) // 2
    
    

    举例分析

    明白了以上几个概念,我们再来说说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。也就是一个赋值复制过程。我们举几个例子分析下。

    1. 传递基础类型,函数中不修改参数类型

    
    var a = 1
    
    function func(o) {
    
        o = 2
    
        console.log(o)
    
    }
    
    func(a) // 2
    
    console.log(a) // 1
    
    

    这里的func函数,传递了一个参数o,而参数实际上是函数的局部变量。那么,我们就可以修改函数

    
    var a = 1
    
    function func() {
    
        var o = a // 函数内部的参数变量,赋值函数外部的值
    
        o = 2 // 修改内部变量的值
    
        console.log(o)
    
    }
    
    func(a) // 2
    
    console.log(a) // 1
    
    

    可以得到相同的结果。他们在内存中的变化,如图示意:
    传递基础类型,函数中不修改类型

    从以上图中,我们能清楚的看出,变量a一直等于1,而变量o,由于赋值之后,复制了a的实际值,在内存中开辟了空间,存储在栈中。再执行func函数,修改变量o的值,只会影响其自身。

    2. 传递基础类型,函数中修改类型

    
    var a = 1
    
    function func(o) {
    
        o = {value : 1}
    
        console.log(o)
    
    }
    func(a) // {value: 1}
    
    console.log(a) // 1
    
    

    同理,我们也可以修改这里的函数

    
    var a = 1
    
    function func() {
    
        var  o = a // 函数内部的参数变量,赋值函数外部的值
    
        o = {value : 1} // 修改内部变量的值
    
        console.log(o)  // {value: 1}
    
    }
    func() // {value: 1}
    
    console.log(a) // 1
    
    

    内存中的变化示意图:
    传递基础类型,函数中修改类型

    从以上图中,我们能清楚的看出,变量a一直等于1,而变量o,由于内部参数赋值之后,复制了a的实际值,在内存中开辟了空间,存储在栈中。再执行func函数,修改变量o的值,只会影响其自身。

    3. 传递引用类型,函数中不修改类型

    
    var a = { value : 1 }
    
    function func(o) {
    
        o.value = 2
    
        console.log(o)
    
    }
    
    func(a) // { value : 2}
    
    console.log(a) // {value : 2}
    
    

    同理,我们也可以修改这里的函数

    
    var a = { value : 1 }
    
    function func() {
    
        var  o = a // 函数内部的参数变量,赋值函数外部的值
    
        o.value = 2 // 修改内部变量的值
    
        console.log(o)  // {value: 2}
    
    }
    func() // {value: 2}
    
    console.log(a) // {value: 2}
    
    

    内存中的变化示意图:
    传递引用类型,函数中不修改类型

    从以上图中,我们能清楚的看出,由于变量a是引用类型,通过函数内部参数的赋值复制,传递了引用地址值,那么变量ao会指向同一个内存对象。再执行func函数,修改变量o在堆内存中的值,并没有修改在栈中的引用地址的值。这样,由于变量o和变量a使用的是同一个引用地址,也就是同一个堆内存中的值,那么变量a的值,也就会随着变量o的变化而变化了。

    4. 传递引用类型,函数中修改类型

    
    var a = {value : 1 }
    
    function func(o) {
    
        o = 2
    
        console.log(o)
    
    }
    
    func(a) // 2
    
    console.log(a) // { value : 1}
    
    

    接下来,我们也可以修改这里的函数

    
    var a = { value : 1 }
    
    function func() {
    
        var  o = a // 函数内部的参数变量,赋值函数外部的值
    
        o = 2 // 修改内部变量的值
    
        console.log(o)  // 2
    
    }
    func() // 2
    
    console.log(a) // {value: 1}
    
    

    内存中的变化示意图:
    传递引用类型,函数中修改类型

    由于变量a是引用类型,通过函数内部参数的赋值复制,传递了引用地址值,那么变量ao会指向同一个内存对象。再执行func函数时,改变了变量o的数据类型,变成了基础数据类型,也就切断了引用。这样,变量ao就没有关系了。

    总结

    JavaScript中所有函数参数都是按值传递的。基本类型值,传递的是实际值,引用类型,传递的是引用地址值。

    参考

    JavaScript深入之参数按值传递

    内存空间详解

  • 相关阅读:
    CSS3—— 2D转换 3D转换 过渡 动画
    CSS3——边框 圆角 背景 渐变 文本效果
    CSS3——表单 计数器 网页布局 应用实例
    CSS3——提示工具 图片廓 图像透明 图像拼接技术 媒体类型 属性选择器
    CSS3——对齐 组合选择符 伪类 伪元素 导航栏 下拉菜单
    CSS3——分组和嵌套 尺寸 display显示 position定位 overflow float浮动
    CSS3——盒子模型 border(边框) 轮廓(outline)属性 margin外边距 padding填充
    Eclipse连接数据库报错Local variable passwd defined in an enclosing scope must be final or effectively final
    数据库——单表查询
    数据库——添加,修改,删除
  • 原文地址:https://www.cnblogs.com/weiqinl/p/9497744.html
Copyright © 2011-2022 走看看