ホームページ > 記事 > ウェブフロントエンド > JavaScript が input_javascript スキルに値を割り当てることに起因する基本型の値と参照型の値に関する問題
自分で何かを作っていたところ、問題が発生しました。ブログパークのホームページ右側の検索を例に、コンソールを使って操作します。
次に、データが更新されるとすぐに表示できるように、別の場所から入力にデータを渡す必要があります。
難しいものではないので、理解した通りにやってみました
コードは次のとおりです:
この時点で、id zzk_q の値は Test である必要があります。つまり、入力ボックスに Test が表示されるはずです。しかし結果は。 。
あれ、なぜ変わっていないのですか? メソッドを前後に変更してみましたが、やはり動作しませんでした。もちろん、コードは基本的に同じです。ふと、以前にも同じような問題に遭遇したことを思い出し、そのときの解き方を注意深く思い出した(当時はよく理解していなかったらしく、ただ方法を見つけて通過しただけだった)。コードは次のとおりです。
結果を見てください:
今度はうまくいきました。初めてこの問題に遭遇したとき、私は詳しく考えず、成功したら飛ばしていました。しかし、今回はなぜだろうと思い始めました。なぜ?どうしてこんなことが起こるのでしょうか?それからどこに行こうかと行ったり来たりしましたが、それでもわかりませんでした。同じ課題でもこの 2 つに違いはありますか?違いは何ですか?後でそれが値型と参照型であることを知りました。もちろん、他の人が私に指摘してくれました (…)。
そこで、このエリアで何かないかと探しに行ったら、これは前にも見たことがあるということを発見しました、汗。
JavaScript は 1997 年に標準化されて以来、6 つの基本型が定義されています。 ES6 までは、JS プログラム内の値は次のいずれかの型に属していました。
•未定義
•ヌル
•ブール値
•番号
•文字列
•オブジェクト
ただし、ES6 では、シンボル型という別の基本型が追加されています。これについてはあまり詳しくないので、詳しくは説明しません。詳しくなってから話します。
JavaScript の変数には、基本型と参照型の値の 2 種類の値があります。プリミティブ型の値 (値型とも呼ばれる) は、値によってアクセスされ、その中の値を操作する単純なデータ セグメントです。参照型の値は、複数の値を持つ可能性のあるオブジェクトです。値を割り当てるとき、インタプリタは値がプリミティブ型であるか参照型であるかを判断する必要があります。
基本的なデータ型には、未定義、Null、ブール、数値、文字列が含まれます。参照型はメモリに格納されるオブジェクト、つまりオブジェクトはメソッドとプロパティの組み合わせです。
1. 型値の動的属性
これは参照型です:
var person = new Object(); person.name = "foo"; console.log(person.name);//foo delete person.name; console.log(person.name)://undefined
この例では、最初に空のオブジェクトを作成し、それを person 変数に保存し、次にオブジェクトに属性名を追加し、この属性に文字列「foo」を割り当てて出力します。文字列 foo が出力される場合は、この属性を削除し、未定義を出力します。これらの手順は、オブジェクトが破棄されない場合、またはプロパティが削除された場合でも、プロパティとメソッドをオブジェクトに動的に追加できることを示しています。
これは基本的なタイプです:
var name = "foo"; name.age = 22; console.log(name.age);//undefined
在这个中,我们将一个字符串"foo",保存在一个name变量中,然后也给它添加了一个属性age,并赋值22,然后输出,像我以前想的那么该输出22,但实际情况是undefined。
这个是否可以理解为基本类型的值是不可变的,而引用类型是可以动态改变的。
2.复制变量值
和上面说的一样,基本类型是按值访问的。而引用类型呢,在JavaScript和其它语言不同,允许直接访问内存中的位置,也就是说我们不可以直接操作对象的内存空间,那怎么办呢?在操作对象时,实际上是对操作对象的引用,引用类型的值是按引用对象访问的。引用类型的存储需要内存的栈内存和堆内存共同完成,栈内存保存变量标识符和指向堆内存中该对象的指针,也可以说是该对象在堆内存的地址。
先看例子:
var num1 =5; var num2 =num1;//5 num1+=1; //6 num2;//5
从一个变量向另一个变量复制基本类型的值,我们会在变量对象上重新创建一个新值,然后把该值复制到新变量分配的位置上。这俩个值是完全对立的,对俩个变量进行其他操作是互不影响的。它们应该是保存在栈内存中,如下图所示:
看一下引用类型:
var obj1 = new Object(); var obj2 = obj1; obj1.name = "foo"; console.log(obj2.name); //foo obj2.age = 22; console.log(obj1.age); //22
当从一个变量想另一个变量复制引用类型的的值时,也会将该值复制一份放到新的空间中。但是就跟上面说的一样,引用类型的存储要栈内存和堆内存一起完成,这个值实际上是一个指针,而这个指针指向存储在堆中的一个对象。复制操作结束后,俩个变量实际上是同一个指针,也就是引用同一个对象。所以,改变其中的一个变量,另一个变量也会随之改变。如下图:
参看 JavaScript高级程序设计。
这样一梳理,就对一开始的问题有些明白了,开头那个错误,一开始,取到input的value(此时为空),复制给title,然后以改变title期望改变input的value。但input的value(可以看成一个变量)就是一个基本类型,复制后,它俩完全独立了,互不影响。再说成功的,将value拿出来,先将input(对象)复制给title,然后给title添加value属性,并赋值,此时俩个指向同一个对象,改变一个,也会影响另外一个。恩,就这样子。
虽然很多知识从书上或其他地方看了一遍或多遍,但是等你真正遇到时感觉好奇怪。怎么会这样,然后自己去找答案。等找到或是别人指出后,才发现这个以前看见过,有些甚至自己解决过(不能说解决,只能说没有深究,没有彻底弄懂)。还有一些大学的基础都忘的七七八八了(本来就学的不好)。连栈内存和堆内存都去搜了一下。恩,既然决定走这条路了,就好好学习吧。
最后:
Good good coding,day day up!
PS:(集合和引用类型、基本数据类型赋值不一样)一个简单的java问题 先后的赋值问题
<span style="white-space:pre"> </span>List<person> list = new ArrayList<person>(); <span style="white-space:pre"> </span>person pp = new person(); <span style="white-space:pre"> </span>list.add(pp); <span style="white-space:pre"> </span>pp.setIvalue(12); <span style="white-space:pre"> </span>pp.setIvalue(20); <span style="white-space:pre"> </span>pp = null;; <span style="white-space:pre"> </span>int b = 0; <span style="white-space:pre"> </span>int a = b; <span style="white-space:pre"> </span>b = 8; <span style="white-space:pre"> </span>System.out.println(a); <span style="white-space:pre"> </span>for (person ppp : list) { <span style="white-space:pre"> </span>ppp.getIvalue(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>
list里面的对象加进去就改不了,但是可以修改对象里面的属性值。
简单string里面的值就改变不了
结果:
11
8888
切记:最好还是按正常来写,避免混淆