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

推薦する

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

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

MySQL マルチバージョン同時実行制御メカニズム (MVCC) ソースコードの詳細な説明

目次1. はじめに2. MVCC (マルチバージョン同時実行制御メカニズム) 2.1 繰り返し読み取...

Swiper.jsプラグインを使用すると、カルーセル画像を非常に簡単に実装できます。

Swiper は、携帯電話やタブレットなどのモバイル端末向けに設計された、純粋な JavaScri...

行間隔が広い場合の解決策(IE では 5 ピクセル多い)

コードをコピーコードは次のとおりです。 li {幅:300px; 高さ:23px; 行の高さ:24p...

Mac 向け MySQL 5.7.17 のインストールと設定のチュートリアル

1. MySQLをダウンロードする公式サイトのダウンロードページをクリックすると次のページに入ります...

SQL実装 LeetCode (176. 2番目に高い給与)

[LeetCode] 176. 2番目に高い給与従業員テーブルから 2 番目に高い給与を取得する ...

クリーンなコードのための Web デザインの 12 の法則 [グラフィック]

美しいコードは美しい Web サイトの基礎です。優れた CSS は、同様に優れた HTML の上にの...

階段を転がす特殊効果を実現する JavaScript (jQuery 実装)

皆さんもJDを使ったことがあると思います。ホームページには非常によく見られる機能があります。階段の特...

シンプルな計算機を実装するためのネイティブ js

この記事の例では、参考までに簡単な計算機を実装するためのjsの具体的なコードを共有しています。具体的...

Vue-Routerのルート設定の詳しい説明

目次導入ルート内のオブジェクト属性パス: 文字列コンポーネント: コンポーネント | () =>...

49 個の JavaScript のヒントとコツ

目次1. js整数の演算2. ネイティブアラートを書き換えてポップアップボックスの数を記録する3. ...

開発効率の向上に役立つ 56 個の実用的な JavaScript ツール関数

目次1. デジタルオペレーション(1)指定された範囲内で乱数を生成する2. 配列操作(1)配列の順序...

Linux ファイルを分割するための split コマンドの詳細な説明

いくつかの簡単な Linux コマンドを使用すると、ストレージまたは電子メールの添付ファイルのサイズ...

MySQLのインストール時に発生する可能性のある問題

質問1:インストール中に net start mysql と入力すると、次のエラー メッセージが表示...

node.js でマルチコア CPU を最大限に活用する方法

目次概要node.js でマルチコア CPU を最大限に活用する方法Node で子プロセスを作成する...