ホームページ > 記事 > ウェブフロントエンド > jsの変数、スコープ、メモリを詳しく解説_基礎知識
基本的な型の値には、未定義、NUll、Boolean、Number、String が含まれます。これらの型はメモリ内の固定サイズの領域を占有し、値によってアクセスします。
(1) 値の型: 数値、ブール値、null、未定義。
(2) 参照型: オブジェクト、配列、関数。
割り当てられた値が参照型の場合、ヒープ メモリ内でこの値用の領域を割り当てる必要があります。このような値のサイズは固定されていないため (オブジェクトには多くのプロパティとメソッドがあります)、スタック メモリに保存できません。ただし、メモリアドレスのサイズは固定されているため、メモリアドレスをスタックメモリに保存できます。
<script type="text/javascript”> var box = new Object(); //创建一个引用类型 var box = "lee"; //基本类型值是字符串 box.age = 23; //基本类型值添加属性很怪异,因为只有对象才可以添加属性。 alert(box.age); //不是引用类型,无法输出; </script>
つまり、ヒープメモリには参照値が格納され、スタックメモリには固定型の値が格納されます。
<script type="text/javascript"> var man = new Object();//man指向了栈内存的空间地址 man.name = "Jack"; var man2 = man;//man2获得了man的指向地址 alert(man2.name);//两个都弹出Jack alert(man.name); </script>
変数値をコピー
次の例を見てください:
<script type="text/javascript"> var man = new Object();//man指向了栈内存的空间地址 man.name = "Jack"; var man2 = man;//man2获得了man的指向地址 man2.name = "ming";//因为他们都指向同一个object,同一个name,不管修改谁,大家都修改了 alert(man2.name);//两个都弹出ming alert(man.name); </script>
上記のことから、変数のコピーに関しては、基本型と参照型も異なります。基本型は値そのものをコピーするのに対し、参照型はアドレスをコピーします。
パラメータを渡す
ECMAScript では、すべての関数パラメーターは値によって渡されます。
<script type="text/javascript"> function box(num){ //按值传递 num+=10; return num; } var num = 10; var result = box(num); alert(result); //如果是按引用传递,那么函数里的num会成为类似全局变量,把外面的number替换掉 alert(num); //也就是说,最后应该输出20(这里输出10) </script>
JavaScript は参照渡しではありません。参照渡しがある場合、関数内の変数はグローバル変数となり、外部からアクセスすることもできます。しかし、これは明らかに不可能です。
実行環境と範囲
実行環境は、JavaScript の最も重要な概念の 1 つであり、変数または関数が他のデータにアクセスするための権限を定義します。
グローバル実行環境は、Web ブラウザーではウィンドウ オブジェクトであるため、グローバル変数の関数はすべてウィンドウのプロパティとメソッドとして作成されます。
<script type="text/javascript"> var name = "Jack"; //定义全局变量 function setName(){ return "trigkit4"; } alert(window.name); //全局变量,最外围,属于window属性 alert(window.setName()); //全局函数,最外围,属于window方法 </script>
実行環境内のコードが実行されると、環境は破棄され、その環境に保存されている変数や関数も破棄されます。グローバル環境の場合は、すべてのプログラムが実行されるか、実行環境が完了するまで破棄されません。ウェブページが完成しました。
var のローカル変数を削除します
<script type="text/javascript"> var name = "Jack"; function setName(){ name = "trigkit4"; //去掉var变成了全局变量 } setName(); alert(name);//弹出trigkit4 </script>
パラメータを渡すことでローカル変数にもなります
<script type="text/javascript"> var name = "Jack"; function setName(name){ //通过传参,也是局部变量 alert(name); } setName("trigkit4");//弹出trigkit4 alert(name);//弹出Jack </script>
関数本体にも関数が含まれています。この関数のみが関数の内部層にアクセスできます。
<script type="text/javascript"> var name = "Jack"; function setName(){ function setYear(){ //setYear()方法的作用域在setName()内 return 21; } } alert(setYear());//无法访问,出错 </script>
次の方法でアクセスできます:
<script type="text/javascript"> var name = "Jack"; function setName(){ function setYear(){ //setYear()方法的作用域在setName()内 return 21; } return setYear(); } alert(setName()); //弹出21 </script>
別のスコープの例:
<script type="text/javascript"> var name = "Jack"; function setName(){ function setYear(){ //setYear()方法的作用域在setName()内 var b = "hi"; //变量b的作用域在setYear()内 return 21; } alert(b);//无法访问 } </script>
環境内でコードが実行されると、スコープ チェーンと呼ばれるものが形成されます。その目的は、実行環境内でアクセス権を持つ変数や関数に確実にアクセスできるようにすることです (アクセスするためのルール階層を指します)。 、スコープ チェーンのフロント エンドは、実行環境の変数オブジェクトです。
範囲
関数内で宣言されていないか、var なしで宣言されている変数はグローバル変数です。ウィンドウ オブジェクトのすべてのプロパティは、コード内のどこからでもアクセスできます。変数はローカル変数であり、関数本体内でのみ使用できます。関数のパラメーターは var を使用しませんが、それでもローカル変数です。
ブロック範囲なし
ブロックスコープなし
// if语句: <script type="text/javascript"> if(true){ //if语句的花括号没有作用域的功能。 var box = "trigkit4"; } alert(box);//弹出 trigkit4 </script>
for ループ文についても同様です。
変数のクエリ
変数クエリでは、ローカル変数へのアクセスはグローバル変数よりも高速であるため、スコープ チェーンを検索する必要はありません。
以下の例:
<script type="text/javascript"> var name = "Jack"; function setName(){ var name = "trigkit4"; return name; //从底层向上搜索变量 } alert(setName()); </script>
メモリの問題
JavaScript には自動ガベージ コレクション メカニズムがあり、データが使用されなくなったら、「null」に設定して参照を解放できます。
循環参照
非常に単純な例: DOM オブジェクトは Javascript オブジェクトによって参照され、同時に同じまたは別の Javascript オブジェクトを参照します。この DOM オブジェクトはメモリ リークを引き起こす可能性があります。この DOM オブジェクトへの参照は、スクリプトの停止時にガベージ コレクターによって再利用されません。参照サイクルを中断するには、DOM 要素を参照するオブジェクトまたは DOM オブジェクトへの参照に null を割り当てる必要があります。
閉店
クロージャの外にある変数がクロージャに導入された場合、クロージャの終了時にオブジェクトをガベージコレクション(GC)することはできません。
var a = function() { var largeStr = new Array(1000000).join('x'); return function() { return largeStr; } }();
DOM リーク
元の COM が削除されると、子ノード参照は削除されない限り再利用できません。
var select = document.querySelector; var treeRef = select('#tree'); //在COM树中leafRef是treeFre的一个子结点 var leafRef = select('#leaf'); var body = select('body'); body.removeChild(treeRef); //#tree不能被回收入,因为treeRef还在 //解决方法: treeRef = null; //tree还不能被回收,因为叶子结果leafRef还在 leafRef = null; //现在#tree可以被释放了。
タイマーが漏洩しました
タイマーもメモリ リークが発生する一般的な場所です。
for (var i = 0; i < 90000; i++) { var buggyObject = { callAgain: function() { var ref = this; var val = setTimeout(function() { ref.callAgain(); }, 90000); } } buggyObject.callAgain(); //虽然你想回收但是timer还在 buggyObject = null; }
デバッグメモリ
Chrome の組み込みメモリ デバッグ ツールを使用すると、メモリ使用量とメモリ リークを簡単にチェックできます:
タイムラインのレコードをクリックします ->