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 BEM 記述標準の詳細な説明

BEM は、Web 開発に対するコンポーネントベースのアプローチです。ユーザー インターフェイスを独...

ラベルタグを使用してテキストをクリックしてラジオボタンを選択します

<label> タグは、入力要素のラベル (タグ) を定義します。ラベル要素はユーザーに...

CocosCreator で http と WebSocket を使用する方法

目次1. HTTPGET 2. HTTP POSTウェブソケット4. Egretのhttpとwebs...

MySQL統計データテーブルの設計方法

目次リアルタイム更新は必要ですか?マテリアライズド ビュー ツール (Flexviews)カウントテ...

Javascript イベントキャプチャとバブリングメソッドの詳細な説明

目次1. イベント処理モデル1. イベントバブリング(1)3つのdiv要素にイベントをバインドする(...

ウェブページ作成時のHTMLタグの使用に注意してください

この記事では、Web ページの作成を学習するときに注意すべき HTML タグに関するいくつかの問題を...

Linux で Nginx 1.16.0 をインストールするための詳細なチュートリアル

最近 Linux をいじっていたので、nginx の新しいバージョンをインストールしたいと思いました...

Tomcat マルチレイヤーコンテナの設計に関する簡単な説明

目次コンテナ階層サーブレットの検索を要求するプロセス仕組みTomcat のコンテナは Servlet...

HTML の ReadOnly と Enabled の違い

ReadOnly 属性を持つ TextBox は、クライアント上で次のマークアップとして表示されます...

美しい FLASH ウェブサイト デザイン例 50 選

Flashにより、デザイナーや開発者はブラウザ上でリッチなコンテンツを提供し、動き、インタラクティブ...

Vueは2つのルーティング許可制御メソッドを実装しています

目次方法 1: ルーティング メタ情報 (meta)方法 2: ルーティング テーブルを動的に生成す...

MySQLトリガーについて深く理解するための記事

目次1. SC テーブルを挿入または変更するときに、テスト スコアが 0 ~ 100 の範囲外の場合...

Centos7.5でのIPアドレス設定の実装

1. IPアドレスを設定する前に、まずifconfigを使用してネットワークカード情報を表示し、ネッ...

Mysql 5.7.19 無料インストール バージョンで遭遇した落とし穴 (コレクション)

1. 公式ウェブサイトから 64 ビットの zip ファイルをダウンロードします。 2. インスト...

MySQL の最初のインストールが成功した後にパスワードを初期化する手順

ファイルをディレクトリに解凍しますこれは解凍後のディレクトリですmy.iniファイルを入力しますダブ...