JavaScriptにおける評価戦略の詳細な説明

JavaScriptにおける評価戦略の詳細な説明

私は最近、JavaScript のラムダ計算における η 変換の応用を勉強していたのですが、偶然、stackoverflow で興味深い質問を見かけました。 JavaScript の評価戦略に関して、js 内の関数のパラメータの受け渡しは値渡しですか、それとも参照渡しですか?答えは古典的です。

それを覆う栗

関数 changeStuff(a, b, c) {
  a = a * 10;
  b.item = "変更されました";
  c = {item: "変更されました"};
}

var 数値 = 10;
var obj1 = {item: "変更なし"};
var obj2 = {item: "変更なし"};

内容を変更します(num、obj1、obj2);

console.log(数値); // 10
console.log(obj1.item); // 変更されました
console.log(obj2.item); // 変更なし

js 内の関数のパラメータ渡しが値渡しである場合、関数 changeStuff 内の b.item の値を変更しても、外部の obj1 オブジェクトの値には影響しません。

JS の関数パラメータが introduction によって渡される場合、関数 changeStuff 内で行われた変更は関数外のすべての変数定義に影響します。num は 100 になり、obj2.item は changed になります。明らかにそうではありません。

したがって、JS での関数パラメータの受け渡しは厳密に値渡しか導入渡しかであるとは言えません。一般に、関数パラメータは値によって渡されます。 JS では、共有渡しと呼ばれるパラメータ渡し戦略も使用されます。パラメータのタイプによって異なります。

パラメータがプリミティブ型の場合、値によって渡されます。

パラメータが参照型の場合、共有として渡されます。

パラメータの受け渡し

ECMAScript のすべての関数パラメータは値によって渡されます。つまり、関数の外部の値を関数内のパラメータにコピーすることは、ある変数から別の変数に値をコピーすることと同じです。プリミティブ型の値の転送はプリミティブ型の変数のコピーと同じであり、参照型の値の転送は参照型の変数のコピーと同じです。 -- 高度な JavaScript プログラミング

レッドブックには、すべての関数パラメータは値によって渡されると書かれています。これは本当ですか?上記の例を分析してみましょう。

値渡し

JavaScript でパラメータとしてプリミティブ型を使用する場合の戦略は、値渡し(値による呼び出し)です。

関数foo(a) {
  a = a * 10;
}

var 数値 = 10;

foo(数値);

console.log(num); // 10 変更なし

ここで、関数の内部パラメータの変更は外部変数に影響を与えないことがわかります。値渡しは正しいです。

共同配送

JavaScript でオブジェクトをパラメータとして渡す戦略は、共有による呼び出しです。

パラメータのプロパティを変更すると外部オブジェクトに影響します

再割り当ては外部オブジェクトには影響しません

上記の例では、関数内でパラメーター b のプロパティ項目が変更され、関数外のオブジェクトに影響するため、obj1 のプロパティ項目も変更されます。

関数バー(b) {
  b.item = "変更されました";
  console.log(b === obj1) // 真
}

var obj1 = {item: "変更なし"};

バー(obj1);

console.log(obj1.item); // changed パラメータのプロパティを変更すると、外部オブジェクトに影響します

b === obj1 の印刷結果が true であることから、関数内でパラメータの属性を変更しても、パラメータの参照には影響しないことがわかります。 b と obj1 はオブジェクト アドレスを共有しているため、パラメーターのプロパティを変更すると外部オブジェクトに影響します。

パラメータ c を新しいオブジェクトに再割り当てしても、外部オブジェクトには影響しません。

関数 baz(c) {
  c = {item: "変更されました"};
  console.log(c === obj2) // 偽
}

var obj2 = {item: "変更なし"};

obj2 を 0 にセットします。

console.log(obj2.item); // 未変更 再割り当ては外部オブジェクトには影響しません

パラメータ c を新しいオブジェクトに再割り当てすると、c は新しいオブジェクト アドレスにバインドされ、c === obj2 は false を出力し、同じオブジェクト アドレスを共有しなくなったことを示します。それぞれに個別のオブジェクト アドレスがあります。したがって、再割り当ては外部オブジェクトに影響しません。

要約する

共有による受け渡しは、参照アドレスのコピーが渡される、値渡しの特殊なケースであると言えます。つまり、リトル・レッド・ブックに書かれていることは正しいのです。

ECMAScript 関数のパラメータはローカル変数と考えることができます。 -- 高度な JavaScript プログラミング

拡張機能 - 遅延評価

先ほど、すべての関数パラメータは値によって渡されることを学びました。 JavaScript では、パラメータは最初に評価され、実際のパラメータとして関数に渡される必要があります。しかし、ES6 には特別なケースがあります。

パラメータのデフォルト値は値渡しされませんが、デフォルト値式の値は毎回再計算されます。つまり、パラメータのデフォルト値は遅延評価されます。 -- 「ECMAScript 6 入門」

x = 99 とします。
関数foo(p = x + 1) {
  コンソールにログ出力します。
}

関数foo() // 100

100 です
関数foo() // 101

上記のコードでは、パラメーター p のデフォルト値は x + 1 です。このとき、関数fooが呼び出されるたびに、デフォルトのpが100に等しい代わりにx + 1が再計算されます。

上記は、JavaScript の評価戦略に関する詳細な説明です。JavaScript の評価戦略の詳細については、123WORDPRESS.COM の他の関連記事をご覧ください。

以下もご興味があるかもしれません:
  • JavaScript徹底理解シリーズ(19):評価戦略(評価戦略)詳細解説
  • JavaScript メタ循環評価子の書き方
  • JavaScriptの遅延評価を実装する方法の例
  • JSは算術式を評価できる計算機関数の例を実装します
  • JavaScript データ構造におけるスタックの応用における式評価問題の詳細な説明
  • JS クロージャと遅延評価の使用例
  • JavaScript オペランドの評価順序
  • 学生情報管理システムを実装するためのJavaScript+HTML
  • JavaScriptにおけるこのポインティング問題の詳細な説明
  • JavaScriptのプロトタイプオブジェクトを徹底的に理解しましょう

<<:  Nginx での Frp による https への強制リダイレクト設定の詳細な説明

>>:  Macシステムをインストールした後にVMWareがフルスクリーンで表示できない問題を解決する

推薦する

モバイル適応型ウェブページ効果は、小さな表示ページの問題を解決します

仕事上、携帯電話に適応した Web ページ効果を作成する必要があります。ようやく完成しました。まずは...

Linux の一般的なテキスト処理コマンドと vim テキストエディタ

今日は、いくつかの一般的なテキスト処理コマンドとvimテキストエディタを紹介します。 3日目 - 一...

ネイティブjsは9マスグリッドのドラッグアンドドロップを実現します

ネイティブJSを使用して9つの正方形のグリッドを記述し、9つのグリッドの位置をドラッグして変更する効...

js、css、htmlはブラウザのさまざまなバージョンを決定します

正規表現を使用してIEブラウザのバージョンを判別するIEブラウザかどうか確認するif (docume...

Dockerの匿名マウントと名前付きマウントの具体的な使用法

目次データ量匿名マウントと名前付きマウントデータボリュームの場所データ量匿名マウントと名前付きマウン...

vue+echartsチャートの使用に関する問題記録

序文echarts は私が最もよく使用するチャート作成ツールであり、非常に完全なエコシステムとコンテ...

MySQL が uuid または snowflake id を主キーとして使用することを推奨しない理由の詳細な分析

前書き: MySQL でテーブルを設計する場合、MySQL では UUID や非連続かつ非繰り返しの...

Docker を使用して Django プロジェクトをデプロイする方法の例

また、Dockerを使用してDjangoプロジェクトをデプロイするのも非常に簡単です。とても良いです...

MySQL ステートメントにおける IN と Exists の比較分析

背景最近、SQL 文を書くときに、IN と Exists のどちらを選択するか迷ったので、両方の方法...

docker ストレージを使用して Exit を実行すると、サーバーへのファイルのアップロードが失敗する問題と解決策

1. 問題の説明Docker コンテナにインストールされているストレージが終了状態になっているため、...

マインスイーパゲームを実装するための jQuery プラグイン (2)

この記事では、jQueryプラグインを使用してマインスイーパゲームを実装する2番目の記事を参考までに...

Linux での umask の使用に関する詳細な説明

私は最近 Linux を学び始めました。Ma Ge の umask に関する Linux コースを読...

Nginx で何ができるかの包括的な分析

序文この記事は、サードパーティのモジュールをロードせずにNginxで処理できることのみに焦点を当てて...

MySQL データベースの基礎 SQL ウィンドウ関数の例の分析チュートリアル

目次導入導入集計関数 + over()ソート関数 + over() ntile() 関数 + ove...

iframe 適応サイズ実装コード

ページドメインの関係:メインページ a.html はドメイン A: www.jb51.net に属し...