js函数传参是按值传递还是按引用传递?

闲话少述,直切主题

从这个问题出发,首先我们应该知道一个概念,js的基本类型和引用类型有哪些?

基本类型:Number Boolean String Null Undefined
引用类型:Object(对象),在js 中函数和数组也是一个对象 
那为什么说函数也是一个对象

以上图中 简单的代码是创建一个函数的两个方法 
并利用console.dir() 方法打印出它的所有属性和方法


由控制台所得结果看 两者都可以成功创建一个函数

function fn 定义一个具名实际上是 通过 Function() 构造函数 构造出来的一个fn 实例
可从下图得知 js的原型链中 定义 所有的对象都有一个 __proto__属性 这个属性是指向构造函数的prototype

函数相比较于其他类型 也比较特殊 会有两个属性 prototype 和 __proto__ 
prototype 自身原型 和 构造函数__proto__  原型兼有
从__proto__ 可以看出 function 的 构造器(constructor)是 Function()

所以在js 中我们都说function  实际上是 Function() 构造函数实例出来的一个对象


介绍完 js 的基本类型 和 引用类型 我们还要说一下 这些类型 在js 中是怎么样进行存储
在js 中 写下 var a = 10; var obj = {a:10,b:function() { console.log(a) }};
js 到底做了什么事情
1.变量提升 var a; var obj = new Object();a=10;obj = {a:10,b:function() { console.log(a) }};
2.定义变量的同时
基本类型 就在栈中开辟一块空间 命名为a 存储10
引用类型 就在栈中开辟一块空间 命名为obj 但obj 存储的不再是值 而是该对象的指针 每次使用该对象的时候 去堆中获取该指针对应的实例

所以在 js 函数中传参 到底是按值传递还是 按引用传递 就跃然于纸上了 但还有一些特殊情况的

具体解析如下


此时的a 应为 10 
为什么? 背后做了些什么操作
1.将变量a 作为实参 传递给 函数fn 实际上是把 a 变量复制了 一份 传递给了 fn 所以函数内部如何改变传进来的实参 外部a是无影响的
这就是按值传递 按值传递主要是将基本类型作为 实参传递给函数 所遵循的规则

那我们来看 第二种引用 传递
何用引用传递 引用传递的现象又是什么?


此时的obj 应为 {a:20,b:function() {console.log(12345)}} 

为什么? 背后做了些什么操作
1.将变量obj 作为实参 传递给 函数fn 实际上是把 obj 变量的指针给了函数的形参 就是前文中提到的放在栈中的指针 所以函数内部对obj 的属性进行改变 后部的变量也该进行改变

这就是引用传递 引用传递主要是将引用类型作为 实参传递给函数 所遵循的规则

但还有一种特殊情况,请往下看

看到这段代码 你可能会觉得 它应该也是按引用传递的规则

但实际上它不是按引用传递 也不能理解为按值传递 有人将其叫做共享传递 那它怎么情况下出现呢
1.将变量obj 作为实参 传递给 函数fn 实际上是把 obj 变量的指针 就是前文中提到的放在栈中的指针 实际上实参传参给函数的形参依然是传递一个指针(也可称引用)那为什么不是引用传递呢
因为在函数内部 我们处理了一步 就是h = 10 这样我们就将10 这个值传递给了形参 形参现在存储的不再是传进来的实参的指针 所以不管内部形参如何改变 obj都不变
好了 到此终止!!!

你可能感兴趣的:(js函数传参是按值传递还是按引用传递?)