基本數據類型和引用數據類型的區別和變量及做用域(函數和變量)

基本類型和引用類型的值javascript

ECMAScript 變量可能包含兩種不一樣的數據類型的值:基本類型值和引用類型值。java

基本類型值指的是那些保存在棧內存中的簡單數據段,即這種值徹底保存在內存中的一個位置。瀏覽器

而引用類型值則是指那些保存在堆內存中的對象,意思是變量中保存的實際上只是一個指針,這個指針指向內存中的另外一個位置,該位置保存對象。函數

將一個值賦給變量時,解析器必須肯定這個值是基本類型值,仍是引用類型值。spa

基本類型值:指針

有如下幾種:Undefined、Null、Boolean、Number 和 String。這些類型在內存中分別佔有固定大小的空間,他們的值保存在棧空間,咱們經過按值來訪問的。在某些語言中,字符串以對象的形式來表示,所以被認爲是引用類型。ECMAScript放棄這一傳統code

引用類型的值:必須在堆內存中爲這個值分配空間。因爲這種值的大小不固定,所以不能把它們保存到棧內存中。但內存地址大小是固定的,所以能夠將內存地址保存在棧內存中。這樣,當查詢引用類型的變量時,先從棧中讀取內存地址,而後再經過地址找到堆中的值。對於這種,咱們把它叫作按引用訪問。對象

        

 

 

定義基本類型值和引用類型值的區別blog

定義基本類型值和引用類型值的方式是類似的:建立一個變量併爲該變量賦值。可是,當這個值保存到變量中之後,對不一樣類型值能夠執行的操做則截然不同。ip

var box = new Object(); //建立引用類型
box.name = 'Lee'; //新增一個屬性
alert(box.name); //輸出

/*若是是基本類型的值添加屬性的話,就會出現問題了。*/
var box = 'Lee'; //建立一個基本類型
box.age = 27; //給基本類型添加屬性
alert(box.age); //undefined

 

 

 

 

基本類型值和引用類型值在賦值上的區別

在變量複製方面,基本類型和引用類型也有所不一樣。基本類型複製的是值自己,而引用類型複製的是地址。

基本類型

var box = 'Lee';         //在棧內存生成一個 box 'Lee'
var box2 = box;         //在棧內存再生成一個 box2 'Lee'
alert(box); alert(box2); //box2 是雖然是 box1 的一個副本,但它是徹底獨立的。也就是說,兩個變量分別操做時互不影響。
box2 = 'kkkk'; alert(box2)

引用類型

/* 在引用類型中,box2 其實就是 box,由於他們指向的是同一個對象。若是這個對象中的 name 屬性被修改了,box2.name 和 box.name 輸出的值都會被相應修改掉了。 */
var box = new Object(); //建立一個引用類型
box.name = 'Lee';         //新增一個屬性
var box2 = box;         //把引用地址賦值給 box2
alert(box2.name);

                 

 

 

 

函數中傳遞參數是按值傳遞

javaScript 中全部函數的參數都是按值傳遞的,言下之意就是說,參數不會按引用傳遞,雖然變量有基本類型和引用類型之分。

function box(num) {         //按值傳遞,傳遞的參數是基本類型
    num += 10;                 //這裏的 num 是局部變量,全局無效
    return num; } var num = 50; var result = box(num); alert(num); //仍是50
alert(result);    //60 /*以上的代碼中,傳遞的參數是一個基本類型的值。而函數裏的 num 是一個局部變量,和外面的 num 沒有任何聯繫。*/
function box(obj) {           //傳遞的參數是引用類型,可是是按值傳遞的,看似傳遞的是p對象的地址值,實際上是將這個對象直接傳進去的
    obj.name = 'Lee'; } var p = new Object(); box(p); alert(p.name); 
function box(obj) { obj.name = 'Lee'; var obj = new Object(); //函數內部又建立了一個對象
    obj.name = 'Mr.'; //並無替換掉原來的 obj
} var p = new Object(); box(p); alert(p.name); 

 

 

 

執行環境及做用域

執行環境是 JavaScript 中最爲重要的一個概念。執行環境定義了變量或函數有權訪問的其餘數據,決定了它們各自的行爲。

全局執行環境是最外圍的執行環境。在 Web 瀏覽器中,全局執行環境被認爲是 window對象。

所以全部的全局變量和函數都是做爲 window 對象的屬性和方法建立的。

var box = 'blue'; //聲明一個全局變量
function setBox() { console.log(box); //全局變量能夠在函數裏訪問
} setBox(); //執行函數

/*全局的變量和函數,都是 window 對象的屬性和方法*/
var box = 'blue'; function setBox() { console.log(window.box); //全局變量即 window 的屬性
} window.setBox(); //全局函數即 window 的方法
function setBox1(){ function setColor(){ return 322; } return 22; } //console.log(window.setColor()); //結果報錯,由於setColor這個方法是不屬於全局的,沒法直接調用 

函數裏的局部做用域裏的變量替換全局變量,但做用域僅限在函數體內這個局部環境。

var box = 'blue'; function setBox() { var box = 'red';     //這裏是局部變量,出來就不認識了console.log(box);
} setBox(); console.log(box); // blue
var box = 'blue'; function setBox() { box = 'red';     //去掉var就變成全局變量了
} setBox(); console.log(box); // red

經過傳參,能夠替換函數體內的局部變量,但做用域僅限在函數體內這個局部環境。

var box='blue'; function setBox(box){ console.log(box); } setBox('red');  //red
console.log(box);        //blue

函數體內還包含着函數,只有這個函數才能夠訪問內一層的函數。

var box = 'blue'; function setBox() { function setColor() { var b = 'orange'; console.log(box); // blue
    console.log(b);   //orange,只能在這個函數裏面訪問,不能在外部,由於做用域在這裏
 } // console.log(b) // 報錯:b is not defined
  setColor();         //setColor()的執行環境在 setBox()內
} setBox()  

   

 

 

沒有塊級的做用域

塊級做用域表示諸如 if 語句等有花括號封閉的代碼塊,因此,支持條件判斷來定義變量。

if (true) {         //if 語句代碼塊沒有局部做用域
  var box = 'Lee'; } console.log(box); //Lee

for (var i = 0; i < 10; i ++) { //沒有局部做用域
  var box = 'Lee'; } console.log(i); 10 console.log(box); // Lee
/*var 關鍵字在函數裏的區別*/
function box(num1, num2) { var sum = num1 + num2; //若是去掉 var 就是全局變量了
    return sum; } alert(box(10,10)); alert(sum); //報錯,很是不建議不使用 var 就初始化變量,由於這種方法會致使各類意外發生。因此初始化變量的時候必定要加上 var。
var box = 'blue'; function getBox() { return box;             //表明全局 box
}                             //若是加上函數體內加上 var box = 'red' 那麼最後返回值就是 red
console.log(getBox()); //blue

變量查詢中,訪問局部變量要比全局變量更快,由於不須要向上搜索做用域鏈。

 

 

全局變量和局部變量

<script type="text/javascript">
    for(var x = 0;x<3;x++){        //在腳本片斷中定義的變量,是全局變量
        document.write("x="+x); } document.write("X======="+x);//在java中x變量已經釋放,但在js中還可使用x變量
</script>
<script type="text/javascript"> document.write("X======="+x);//在java中x變量已經釋放,但在js中還可使用x變量,甚至在這裏也能夠訪問的到
</script>
var x = 4;//全局的變量
function show(x){//局部的變量
    x = 8; } show(x); document.write("X======="+x);//結果仍是4 

 在函數做用域中能夠訪問到全局做用域的變量,在全局做用域中沒法訪問到函數做用域的變量

function show(){ var x = 8;//這裏是局部變量
} document.write("X======="+x);//這裏訪問不到函數裏的局部變量

 

 

變量做用域的練習

當在函數做用域操做一個變量時,它會先在自身做用域中尋找,若是有就直接使用。

若是沒有則向上一級做用域中尋找,直到找到全局做用域,若是全局做用域中依然沒有找到,則會報錯ReferenceError在函數中要訪問全局變量可使用window對象

var a = 123; function fun(){ console.log(a); // 函數內部沒有變量a,往外面找,結果是123
} fun(); 
var a = 123; function fun(){ console.log(a); // 函數內部有a變量,只是變量的聲明提早了,因此是undefined
  var a = 456; } fun(); console.log(a); // 全局做用域下的a變量,因此是123
var a = 123; function fun(){ console.log(a); // 函數內部沒有聲明變量,因此結果是外部的a變量123
  a = 456; // 修改了外部變量a的值
} fun(); console.log(a); // 結果是456
var a = 123; function fun(a){ console.log(a); // 調用這個函數的時候沒有傳參數,因此形參變量a是undefined
  a = 456; // 無效,由於a變量是行參
} fun(); console.log(a); // 123
var a = 123; function fun(a){ console.log(a); // 123
  a = 456; // 無效,由於a是形參數,出了這個函數就沒有了
  console.log(a) // 456
} fun(123); console.log(a); // 123
相關文章
相關標籤/搜索