おそらく多くの人が
JavaScript を学習する過程で 関数パラメータ送信メソッドの混乱に遭遇したことがあると思いますが、JavaScript での関数呼び出しの知識についてのチュートリアルを共有します。興味がある方は、共有してみましょう
定義
おそらく多くの人が、JavaScript を学習する過程で、関数のパラメータの受け渡し方法について混乱に遭遇したことがあると思います。ソース コードでいくつかの答えを見つけますが、その前に、まずいくつかの概念を明確にしてください。値の受け渡し、reference受け渡しなどの固有の名前を放棄して、英語に戻ります:
参照による呼び出し && 値による呼び出し && 共有による呼び出し
は、それぞれ参照の受け渡しと値の受け渡しとして理解されるものです。 C++。 3 番目の説明はさらに混乱します。公式の説明では、オブジェクトへの参照のコピーを受け取ります。分かりやすい言葉で説明しましょう: オブジェクトは
keyのコレクションとして理解できます。オブジェクトは、キーが指すデータを指します (ここでは、それがポインター実装であるか C++ 参照実装であるかについては詳しく説明しません)。 ) 関数が受け取るのは 変数 コピーの場合、変数にはオブジェクトへの参照が含まれており、値によって渡されます。 すると、関数がパラメータを渡すときに受け取る
objecttype パラメータは、実際には実際のパラメータのコピーであることは明らかです。そのため、オブジェクトのキーが変更されているため、type パラメータのポインタを直接変更することは現実的ではありません。それ自体は参照なので、キーを指して変更することが可能です。
証明いくつかの簡単なコードで証明できます
コード 1: 関数は key が指すデータを変更できます
let func = obj => { obj.name = 'Dosk' }; let obj = {name : 'Alxw'}; console.log(obj); //{ name: 'Alxw' } func(obj) console.log(obj); //{ name: 'Dosk' }
コード 2: 関数は obj
let func = obj => { obj = {} }; let obj = {name : 'Alxw'}; console.log(obj); //{ name: 'Alxw' } func(obj) console.log(obj); //{ name: 'Alxw' }
コード 3:内部 obj と外部 = == の結果は等しい
let def = {name : 'Alxw'}; let func = obj => { console.log(obj === def) }; func(def); //true
つまり、3 番目のコードに何か問題がある可能性があります。obj は def のコピーであるのに、なぜ === 演算が true になるのでしょうか。 === 演算はオブジェクトのメモリ内のアドレスを比較するという意味ではないでしょうか。コピーの場合は 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 が返されるはずです。そうです。これは上記の内容を覆しませんか?実は、いいえ、無視されていることが 1 つあります。つまり、オブジェクトを内部でインスタンス化する場合、Google V8 自体は動的インスタンス化であり、コンパイル言語では動的インスタンス化はヒープ メモリ上でのみ実行できる、つまりポインタのみが実行できることがわかっています。引用します。この結論の証明には Local や Han
dle などの class の実装が必要になるので、簡単な証明方法としては、< の呼び出しをすべて取得する search という方法があります。 code>Object::StrictEquals Code> は、アドレス取得操作なしで直接渡されます。
しかし、値によって渡される変数には Object への参照が含まれているため、理論的には Object も変更できるのに、なぜ 3 番目のコードを変更できないのかと疑問に思う人もいるかもしれません。 Object::StrictEquals
的地方都是直接传入而没有取地址操作。
不过有人会问,既然是值传递的变量包含 Object 的引用,理论上也能够修改 Object 才对,为什么第三段代码不能修改呢?
很简单的道理,因为我们在 Javascript 语言逻辑层次上的所谓的操作,只不过是在调用 Google V8 的实例方的法而已,根本不可能操作到这一地步(当然,潜在的 BUG 不算的 -。-)
重新定义
我觉得到这里可以给 call by sharing 重新解释一下了:
的确,传递的时候是值传递,但是内容包含了 Object 的指针,而且不能够修改这个指针,他是多个变量共享的。
另一种简单的证明
来来来,看源码
V8_DEPRECATE_SOON("Use maybe version", Local<Value> Call(Local<Value> recv, int argc, Local<Value> argv[])); V8_WARN_UNUSED_RESULT MaybeLocal<Value> Call(Local<Context> context, Local<Value> recv, int argc, Local<Value> argv[]);
上面的是即将弃用的接口,碰巧我看到的这个版本代码包含大量的这种即将弃用的代码,看看就好。重点是第二个接口,是函数的唯一的调用的接口。里面的 Local<Value>
最终会调用 C++ 的位复制,所以可以简单的证明就是值传递。
可能是重点
别忘了,我们定义的的变量都是类似 Handle<Object>
再定義
🎜🎜ここで共有することで呼び出しを再説明できると思います:🎜🎜確かに、渡すときは値によって渡されますが、コンテンツにはオブジェクトのポインタが含まれており、 not このポインタは変更でき、複数の変数で共有されます。 🎜🎜🎜🎜もう 1 つの簡単な証明🎜🎜🎜🎜さあ、ソース コードを見てください🎜rrreee🎜上記は、間もなく非推奨になる予定の インターフェース🎜、たまたま私が見たこのバージョンのコードには、廃止予定のコードが多数含まれています。ちょっと見てください。焦点は、関数の唯一の呼び出しインターフェイスである 2 番目のインターフェイスにあります。内部のLocal<Value>
は最終的に C++ のビット コピーを呼び出すため、それが値の転送であることを簡単に証明できます。 🎜🎜🎜🎜おそらくこれが重要なポイントです🎜🎜🎜🎜忘れないでください、私たちが定義する変数はすべて Handle<Object>>
の形式であるため、それらの間のオブジェクトは共有されます。 Javascript の変数は Object のインスタンスを直接参照しません!!!🎜🎜🎜🎜最後のもの🎜🎜🎜要するに、理解しにくい、あるいは間違いが含まれているかもしれませんが、JavaScript 言語レベルで特性を判断できることが重要です。
上記は、編集者があなたに紹介した Javascript の関数呼び出しです。ご質問があれば、メッセージを残してください。編集者がすぐに返信します。スクリプト ハウス Web サイトをサポートしてくださった皆様にも感謝いたします。
以上がJavaScriptの関数呼び出しのコード詳細の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。