首页 > 语言 > JavaScript > 正文

深入学习 JavaScript中的函数调用

2024-05-06 15:19:28
字体:
来源:转载
供稿:网友

定义

可能很多人在学习 JavaScript 过程中碰到过函数参数传递方式的迷惑,本着深入的精神,我想再源码中寻找些答案不过在做这件事之前,首先明确几个概念。抛弃掉值传递、引用传递等固有叫法,回归英文:

call by reference && call by value && call by sharing

分别是我们理解的 C++ 中的引用传递,值传递。第三种比较迷惑,官方解释是 receives the copy of the reference to object 。我用通俗的话解释一下:

Object 可以理解为 key 的集合,Object 对 key 指向的数据是引用性质的(这里不深究是指针实现还是C++引用实现),函数接收的是一个变量的 copy,变量包含了 Object 的引用 ,是一个值传递。

那么很明显,函数传参的时候我们接收到的对象型参其实是实参的复制,所以直接更改型参的指向是不可行的;由于 Object 本身的 key 都是引用,所以修改 key 的指向是可行的。

证明

简单来几段代码即可证明

Code 1: 函数能修改 key 指向的数据

let func = obj => { obj.name = 'Dosk' };let obj = {name : 'Alxw'};console.log(obj); //{ name: 'Alxw' }func(obj)console.log(obj); //{ name: 'Dosk' }

Code 2: 函数不能修改 obj

let func = obj => { obj = {} };let obj = {name : 'Alxw'};console.log(obj); //{ name: 'Alxw' }func(obj)console.log(obj); //{ name: 'Alxw' }

Code 3: 内部 obj 和外部 === 结果相等

let def = {name : 'Alxw'};let func = obj => { console.log(obj === def) };func(def); //true

所以第三段代码可能有疑问了,既然 obj 是 def 的复制,为什么 === 操作还能够为真?不是说 === 操作对于 Object 比较的是在内存中的地址么,如果是复制应该是 false 才对啊?

所以我们回到 Google V8 的源码来看这件事。

深入 Google V8

我们来看看源码里严格等于操作代码部分:

bool Object::StrictEquals(Object* that) { if (this->IsNumber()) {  if (!that->IsNumber()) return false;  return NumberEquals(this, that); } else if (this->IsString()) {  if (!that->IsString()) return false;  return String::cast(this)->Equals(String::cast(that)); } else if (this->IsSimd128Value()) {  if (!that->IsSimd128Value()) return false;  return Simd128Value::cast(this)->Equals(Simd128Value::cast(that)); } return this == that;}

看起来应该是最后一种情况,理论上如果 def 和 obj 是不同的对象,那么应该返回 false 才对,这不是推翻了上文所述么?其实不,忽略了一件事,即 Google V8 内部在实例化一个 Object 的时候,本身就是动态实例化,而我们知道在编译型语言中如果动态实例化只能够在堆内存上,即只能够指针引用。这个结论是的证明涉及到 Local 、Handle 等 class 的实现,我觉得太麻烦,有一个简单的证明方式,即搜索源码得到所有调用

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选