41

Javascript の不変変数の意​​味を理解しようとしています。私ができる場合:

var x = "astring";
x = "str";
console.log(x); //logs str` , then why it is immutable?

私が考えることができる唯一の答えは(CIの知識から)、var xは値「astring」を持つメモリブロックへのポインターであり、2番目のステートメントの後、値「str」を持つ別のブロックを指すことです。そうですか?

おまけの質問: Javascript の値の型に戸惑いました。すべての変数はフードの下にあるオブジェクトですか? 偶数と文字列?

4

6 に答える 6

58

は不変です。変数はそうではありません。(プリミティブ) 値への参照を保持します。

string、number、および booleanの 3 つのプリミティブ型には、インスタンスがオブジェクトであるString、Number、Booleanの対応する型があります。ラッパー型
と呼ばれることもあります。

次の値はプリミティブです。

  • 文字列:「こんにちは」
  • 数値: 6、3.14 (JavaScript の数値はすべて浮動小数点)
  • ブール値: true、false
  • null: 通常は明示的に割り当てられます
  • undefined: 通常はデフォルト (自動的に割り当てられる) 値

他のすべての値は、プリミティブのラッパーを含め、オブジェクトです。

そう:

  • オブジェクトはデフォルトで変更可能です
  • オブジェクトは一意の ID を持ち、参照によって比較されます
  • 変数はオブジェクトへの参照を保持します
  • プリミティブは不変です
  • プリミティブは値で比較され、個々の ID はありません

The Secret Life of JavaScript Primitivesが良い説明だと思うかもしれません。

また、ES6 には新しいconstキーワードがあり、スクリプトの実行中に割り当てによって値を変更したり、再宣言したりできない読み取り専用の名前付き定数を作成します。

お役に立てれば!

于 2013-04-20T01:20:12.147 に答える
20

まず、C では「文字列は、最後の elem = '\0' を持つ文字の配列です」。それらは変更可能です。
次のように C で文字列を宣言して初期化すると、次のようになります。

char str[] = "Foo";

あなたが基本的にやっていることは、4 バイトを予約することです (おそらく 8 ビットバイトです。気にしないでください)。str という単語は、この配列の最初の要素へのポインタとして機能します。したがって、次のようにする場合:

str[0] or *(str) = 'G'

次に、新しい配列を作成する代わりに、そのアドレスの値を変更します。str のアドレスを出力することで確認できます。どちらの場合も同じになります。

JavaScript の場合、文字列はプリミティブ型です。文字列に対するすべての操作は、参照ではなく値によって行われます。したがって、これを行うと true が生成されます。

var str1 = "foo";
var str2 = "foo";
str1 === str2; => true

string の初期化は、"foo" に適合するバッファを要求し、名前 str1 をそれにバインドします。それらを不変にするのは、そのバッファーを変更できないことです。したがって、これを行うことはできません:

str1[0] = 'G'

非厳密モードでこのコマンドを実行しても、警告やエラーは発生しませんが、str1 は変更されません。あなたはそれを確認することができます

console.log(str1) => "foo"

しかし、あなたがこれを好きなら:

str1 = "goo"

あなたが実際に行っているのは、「goo」に適合し、識別子 str1 をそれにバインドする新しいバッファを要求していることです。「foo」を含む古いバッファに変更はありません。

では、"foo" はどうなるでしょうか。

Java Script には自動ガベージ コレクタがあります。任意の識別子または ... によって参照できなくなったメモリのチャンクを確認すると、そのメモリは解放されていると見なされます。

同じことがnumber、booleansにも起こります。さて、ラッパーオブジェクトについて!次のように文字列のプロパティにアクセスしようとするときはいつでも:

str1.length;

JavaScript は、String クラスを使用して新しいオブジェクトを作成し、文字列のメソッドを呼び出します。関数呼び出しが戻るとすぐに、オブジェクトは破棄されます。以下のコードでさらに説明します。

var str = "nature"; 
str.does = "nurtures"; //defining a new property; 
console.log(str.does) => undefined

オブジェクトが破壊されたためです。これを試して!

var str = new String("Nature");
str.does = "nurtures";
console.log(str) =>  ??

この str は実際にはオブジェクトです...

結論: C では、単一のスコープで変数名がポインターとして機能します。したがって、int、float、string はすべて変更可能です。しかし、Java Script では、プリミティブ型の変数名は参照ではなく値として機能します

参考文献: C++ 入門プラス、Java Script The Definitive Guide、C by Stephen Kochan

于 2013-07-11T15:21:04.557 に答える
5

あなたは正しいです。文字列 (および数値) は、Java スクリプト (および他の多くの言語) では不変です。変数はそれらへの参照です。「変数の値を変更する」とは、値自体ではなく、変数が参照する文字列 (またはその他のもの) を変更することです。

于 2013-04-20T01:20:22.633 に答える