JAVAScript的變量、作用域和內(nèi)存問(wèn)題

前言:

按照ECMA-262的定義,JavaScript的變量與其他語(yǔ)言的變量有很大的區(qū)別。JavaScript變量松散類(lèi)型的本質(zhì),決定了它只是在特定時(shí)間用于保存特定值的一個(gè)名字而已。由于不存在定義某個(gè)變量必須保存何種數(shù)據(jù)類(lèi)型值得規(guī)則,變量的值以及數(shù)據(jù)類(lèi)型可以在腳本的生命周期內(nèi)發(fā)生改變。盡管從某種角度看,這可能是一個(gè)既有趣又強(qiáng)大,同時(shí)又容易出現(xiàn)問(wèn)題的特性,但JavaScript變量實(shí)際的復(fù)雜程度還遠(yuǎn)不止如此。

目錄大綱

一.基本類(lèi)型和引用類(lèi)型的值

1.賦值變量的值

2.傳參

3.檢測(cè)類(lèi)型

1.操作符typeof
2.操作符instanceof

二.執(zhí)行環(huán)境以及作用

1.arguments介紹

2.延長(zhǎng)作用域鏈

1.with語(yǔ)句
2.try-catch語(yǔ)句

3.js沒(méi)有塊級(jí)作用域

三.垃圾收集機(jī)制

1.標(biāo)記清除

2.引用計(jì)數(shù)

一.基本類(lèi)型和引用類(lèi)型的值

變量包括兩種不同的數(shù)據(jù)類(lèi)型的值
1.基本類(lèi)型指的是簡(jiǎn)單的數(shù)據(jù)段,包括Undefined、Null、Boolean、Number和String。
2.引用類(lèi)型指的是保存在內(nèi)存中,由多個(gè)值組成的對(duì)象。
創(chuàng)建對(duì)象舉例

var person = new Object();
person.name = "Nicholos";

注意
1.Object的‘O’一定大寫(xiě)。
2.直接增加屬性并且賦值。
3.只能給引用類(lèi)型才能添加屬性,是動(dòng)態(tài)地添加屬性。

1.賦值變量的值

基本類(lèi)型的賦值方法與C語(yǔ)言相同,會(huì)增加一個(gè)新的空間用于存放副本,變量保存在棧內(nèi)存中。

var num1= 5;
var num2=num1;
1.png

引用類(lèi)型的值則不同,引用類(lèi)型的值是保存在堆內(nèi)存對(duì)象中,JS不允許直接訪(fǎng)問(wèn)內(nèi)存中的位置,所以引用類(lèi)型的值是按照引用類(lèi)型訪(fǎng)問(wèn)的。當(dāng)一個(gè)變量復(fù)制到另一個(gè)變量中,副本其實(shí)是一個(gè)指針,兩個(gè)對(duì)象指的是同一個(gè)對(duì)象。


2.png

2.傳參

傳參就是把變量的值復(fù)制給函數(shù)內(nèi)部的變量,是復(fù)制值的過(guò)程,永遠(yuǎn)滿(mǎn)足值傳遞的關(guān)系。
引用類(lèi)型也是復(fù)制一個(gè)新的指針,實(shí)際上指的還是同一個(gè)對(duì)象。

function setName(obj){
obj.name ="Ac";
obj = new Object();
obj.name = "Bc";
}
var person =new Object();
setName(person);
//person.name ="Ac";

一開(kāi)始函數(shù)內(nèi)的obj是和person指向同一個(gè)對(duì)象的,但是obj新聲明了一個(gè)對(duì)象,引用類(lèi)型的值不再是指向原來(lái)的對(duì)象的值,而且函數(shù)運(yùn)行完后被銷(xiāo)毀。

3.檢測(cè)類(lèi)型

1.操作符typeof
var s="Nicholas";
var b= true;
var i =22;
var u;
var n= null;
var o= new Object();

alert(typeof s);  //string
alert(typeof b); //boolean
alert(typeof i);  //number
alert(typeof u); //undefine
alert(typeof n); //object
alert(typeof o); //object

null和object都是返回object

2.操作符instanceof
alert(person instanceof Object);// person 是Object嗎?
alert(colors instanceof Array );// colors 是Array嗎?
alert(pattern instanceof RegExp);// pattern 是RegExp嗎?

是的話(huà),就返回一個(gè)true,不是的話(huà)就返回一個(gè)false。

二.執(zhí)行環(huán)境以及作用

執(zhí)行環(huán)境(簡(jiǎn)稱(chēng) 環(huán)境)定義了變量和函數(shù)有權(quán)訪(fǎng)問(wèn)的其他的數(shù)據(jù)。每一個(gè)環(huán)境都有一個(gè)與之關(guān)聯(lián)的變量對(duì)象,環(huán)境中定義的所有變量和函數(shù)都保存在這個(gè)對(duì)象中。
全局環(huán)境是一個(gè)最外圍的執(zhí)行環(huán)境,web中一般認(rèn)為全局環(huán)境是window對(duì)象,全局環(huán)境會(huì)一直運(yùn)行到應(yīng)用退出它所定義的函數(shù)和變量才會(huì)被銷(xiāo)毀。
每個(gè)函數(shù)都有自己的執(zhí)行環(huán)境,當(dāng)執(zhí)行流進(jìn)入一個(gè)函數(shù)時(shí),函數(shù)的環(huán)境就會(huì)被推入一個(gè)環(huán)境棧中,函數(shù)執(zhí)行完后,棧將環(huán)境彈出,把控制權(quán)返回給之前的執(zhí)行環(huán)境。
當(dāng)函數(shù)在一個(gè)環(huán)境中執(zhí)行的時(shí)候,會(huì)創(chuàng)建一個(gè)作用域鏈,是為了保證對(duì)執(zhí)行環(huán)境有權(quán)訪(fǎng)問(wèn)的所有變量和函數(shù)有序的訪(fǎng)問(wèn),作用域鏈的前端,始終都是當(dāng)前執(zhí)行代碼所在環(huán)境中變量對(duì)象。如果環(huán)境是函數(shù),將其活動(dòng)對(duì)象作為變量對(duì)象?;顒?dòng)對(duì)象最開(kāi)始只包含一個(gè)變量-----arguments(arguments在全局環(huán)境中不存在)對(duì)象,作用域鏈的下一個(gè)變量對(duì)象來(lái)自包括外部的環(huán)境,一直延續(xù)到全局執(zhí)行環(huán)境。

1.arguments介紹

arguments是JS中每個(gè)函數(shù)(除全局環(huán)境外)都有的類(lèi)數(shù)組對(duì)象,用于儲(chǔ)存函數(shù)傳入的參數(shù)。

  • arguments.length 記錄參數(shù)個(gè)數(shù)。
  • arguments.callee 儲(chǔ)存調(diào)用這個(gè)函數(shù)的代碼。
  • arguments可以實(shí)現(xiàn)函數(shù)的重載。
function add() {
    var len = arguments.length,
        sum = 0;
    for(;len--;){
        sum += arguments[len];
    }
    return sum;
}

console.log( add(1,2,3) );   //6
console.log( add(1,3) );     //4
console.log( add(1,2,3,5,6,2,7) );   //26

標(biāo)識(shí)符解析是沿著作用域鏈一級(jí)一級(jí)的搜索標(biāo)識(shí)符的過(guò)程,從作用域鏈的前端開(kāi)始,逐級(jí)地向后回溯,直到找到標(biāo)識(shí)符為止。
搜索標(biāo)識(shí)符舉例:

      var scope = "global";   //全局
      function fn1(){
         return scope; 
      }
      fn2();
作用域鏈

函數(shù)嵌套的作用域鏈舉例:

  <script>
      function outer(){
         var scope = "outer";
         function inner(){
            return scope;
         }
         return inner;
      }
      var fn = outer();
      fn();
   </script>
作用域鏈

說(shuō)明:當(dāng)調(diào)用outer函數(shù),inner函數(shù)的作用域鏈已經(jīng)初始化了(即復(fù)制父函數(shù)的作用域鏈,再在前端插入自己的活動(dòng)對(duì)象)

2.延長(zhǎng)作用域鏈

1.with語(yǔ)句:

作用:接收一個(gè)對(duì)象,將指定對(duì)象添加到作用域鏈中。
with語(yǔ)句使用方法:

with(people) 
{ 
       var str = "姓名: " + name + "<br>"; 
       str += "年齡:" + age + "<br>"; 
       str += "性別:" + gender; 
       document.write(str); 
} 

優(yōu)點(diǎn)是不用多次寫(xiě)對(duì)象的名字,在代碼塊里直接使用對(duì)象的值,但是注意with語(yǔ)句內(nèi)不能改變對(duì)象的屬性,改變對(duì)象的屬性還是要引用對(duì)象來(lái)改變。

2.try-catch語(yǔ)句:

作用:catch語(yǔ)句產(chǎn)生一個(gè)新對(duì)象添加到作用域鏈的前端,主要用來(lái)檢測(cè)代碼中的錯(cuò)誤。
try-catch的用法:

try{
    //可能會(huì)導(dǎo)致出錯(cuò)的代碼
}catch(error){
  alert("catch an error");
}

當(dāng)try運(yùn)行的代碼運(yùn)行出現(xiàn)錯(cuò)誤的時(shí)候,就會(huì)立即退出代碼進(jìn)程,執(zhí)行catch語(yǔ)塊,catch接收到一個(gè)包含錯(cuò)誤對(duì)象的信息,對(duì)象下的message是包含錯(cuò)誤信息,對(duì)象的名字要自己起。

3.JS沒(méi)有塊級(jí)作用域

花括號(hào)的邊界表示一個(gè)塊,但是在JS中,花括號(hào)封閉的的代碼中聲明的變量會(huì)添加到當(dāng)前的執(zhí)行環(huán)境。

if(true){
   var color="blue";
}
alert(color); //blue

用關(guān)鍵字let讓生命的變量只在塊作用域內(nèi)有效。

for(let i=0;i<5;i++){
  //操作
}
alert(i); //ReferenceError: i is not defined

三.垃圾收集機(jī)制

JS中會(huì)自動(dòng)找出不再使用的變量,釋放其占用的內(nèi)存,按照固定是時(shí)間間隔,周期性地重復(fù)操作。

1.標(biāo)記清除

當(dāng)變量進(jìn)入環(huán)境的時(shí)候就標(biāo)記“進(jìn)入環(huán)境”,當(dāng)環(huán)境離開(kāi)環(huán)境的時(shí)候就標(biāo)記為“離開(kāi)環(huán)境”。

2.引用計(jì)數(shù)

引用計(jì)數(shù)是根據(jù)每個(gè)變量使用的次數(shù)。
1.聲明一個(gè)變量并且將引用類(lèi)型的值賦值給該變量,這個(gè)的引用次數(shù)加一。
2.同一個(gè)值賦值給另一個(gè)變量,該值的引用次數(shù)加一。
3.包含這個(gè)值的引用變量又取得了另外一個(gè)值,該值的引用次數(shù)減一。
4.該值的引用次數(shù)變成0時(shí),等待垃圾收集器運(yùn)行時(shí)釋放該值所占的內(nèi)存。

但是此機(jī)制有弊端:

function problem(){
     var  a =new Object();
     var  b =new Object();
     
     a.some = b;
     b.some = a;
}

例子中的兩個(gè)對(duì)象通過(guò)各自的屬性相互引用,兩個(gè)對(duì)象的引用次數(shù)都是2,不會(huì)是0。

參考文獻(xiàn):

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容