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がフルスクリーンで表示できない問題を解決する

推薦する

CSSの絶対と相対について

冒頭にこう書かれています:アブソリュートは言った。「親戚よ、私はあなたを私の人生で見たくない!」なぜ...

MySQLをインストールして設定し、ルートパスワードを変更する方法

1. インストールapt-get install mysql-server にはアカウントとパスワー...

MySQL の「特殊キーが長すぎます」の解決策

目次解決策1解決策2テーブルを作成するときに、興味深い問題に遭遇しました。「指定されたキーが長すぎま...

IE6 フォントを定義できません: 13px サイズは無効です。IE6 は自動的に大きいフォント ソリューションを表示します。

数日前、Web ページのモジュールを調整していたとき、ページのフォント サイズを 13px に設定し...

Vue+EChartsは、中国の地図の描画と省の自動回転と強調表示を実現します。

目次成果を達成する完全なコード + 詳細なコメントまとめ成果を達成する完全なコード + 詳細なコメン...

ウェブデザインでテキストのサイズを合わせる方法: 小さなテキスト、大きな体験

iPadなどのモバイル端末の普及により、人々がモバイル端末で読書に費やす時間はますます長くなり、読...

Ubuntu Server 16.04 MySQL 8.0 のインストールと設定のグラフィックチュートリアル

Ubuntu Server 16.04 MySQL 8.0 のインストールと設定のグラフィックチュー...

Node.jsはブレークポイント再開を実装する

目次ソリューション分析スライス履歴書のダウンロード具体的な解決プロセス論理的分析フロントエンドサーバ...

ローカル写真をアップロードする前にプレビューコード例を実装するための HTML5 と jQuery

HTML5 と jQuery はアップロード前にローカル画像のプレビューを実装しており、その効果は...

Tomcatの起動が遅い問題を素早く解決、超簡単

今日、私はクラスメートが問題を解決するのを手伝いました - Tomcat の起動が非常に遅く、約 5...

Vue ルーティングフォールバックに最適なソリューション (vue-route-manager)

目次ルーティングマネージャー背景はじめる問題を解決する方法要約するルーティングマネージャー各ジャンプ...

docker-compose でデプロイしたときに MySQL にアクセスできなくなる問題の簡単な分析

Docker-ComposeとはCompose プロジェクトは、以前の fig プロジェクトから派生...

Ubuntu 20.04 に Python 3 仮想環境をインストールする詳細なチュートリアル

以下はすべて仮想マシン上で実行されます1. pip3をインストールするsudo apt で pyth...

MySQL 8.0.11 の新機能の紹介

MySQL 8.0 for Windows v8.0.11 公式無料バージョン 64 ビット1. デ...

CSS ボックスモデル内のパディングと略語の詳細な説明

上図のように、パディング値は時計回り(右上、右下)の複合属性であり、パディングの内側の余白がボックス...