關於Javascript基本類型和引用類型小知識

ECMAScirpt 變量有兩種不一樣的數據類型:基本類型引用類型javascript

基本的數據類型有:undefinedbooleannumberstringnull. 基本類型的訪問是按值訪問的,就是說你能夠操做保存在變量中的實際的值。JavaScript中除了上面的基本類型以外就是引用類型了。java

區別以下:
基本類型:segmentfault

  • 佔用空間固定,保存在棧中
  • 保存與復製的是自己
  • 使用typeof檢測數據類型
  • 值類型

引用類型:函數

基本類型是不會改變,衹能從新賦值,而引用類型值是能夠改變的指針

var a = '123456789',
      b = a;
 
a = '321';
console.log(a) // 321
console.log(b) // 123456789

上面因為是把值保存在了變量了 而不是保存的是引用地址,因此他們兩個是相對獨立的總體,互不影響。可是若是換成引用類型的話code

var a = {
    n: '123456789'
},
b = a;

a.n ='321';
console.log(a) // { n: '321' }
console.log(b) // { n: '321' }

緣由在於在javascript語言中建立的對象值中其保存的是對象的引用(也就是一個地址.引用類型值保存在內存中,而JS是不能直接訪問內存的,因此對於引用類型,操做的不是實際的對象而是對象的引用。)對象

這裏有個小提示説一下,假如兩個相同的基本類型或引用類型(內容同樣)相比,看看結果是怎樣的?ip

var base1 = '123',
    base2 = '123',
    obj1 = { a: '123' },
    obj2 = { a: '123' };

console.log(base1 === base2) // true
console.log(obj1 === obj2) // false

若是你還錯了那就證實你沒理解透上面的東西了,由於前面是值之間直接比較,後面是指向地址的比較,即便兩個引用類型看起來同樣,衹要不是同一個聲明變量,它們就必定不一樣。內存

知識一:基本類型值就是簡單的數據段;引用類型值保存的是對象的引用,不是實際的對象。

可是在函數中的對象傳值又是否是同一回事呢?看看下面代碼ci

function setName(obj) {
    obj.name = '1';
    obj = {};
    obj.name = '2';
}

var obj = {};
setName(obj);

console.log('最終結果obj:', obj) // 最終結果obj: { name: '1' }

沒錯,結果出乎意料的是1.而不是大多數人剛開始認爲的2.
接下來咱們在一步步分析出在函數過程當中對象發生了什麼樣的變化?稍微修改下對象名便於區分。

function setName(innerObj) {
    console.log('初始的innerObj:', innerObj); // 初始的innerObj: {}

    innerObj.name = '1';
    console.log('第一次設置屬性值的innerObj:', innerObj); // 第一次設置屬性值的innerObj: { name: '1' }

    //保存下原對象
    var _innerObj = innerObj;

    innerObj = {};
    console.log('從新賦值的innerObj:', innerObj); // 從新賦值的innerObj: {}

    innerObj.name = '2';
    console.log('第二次設置屬性值的innerObj:', innerObj); // 第二次設置屬性值的innerObj: { name: '2' }

    console.log('二者之間是否是同一個對象?:', _innerObj == innerObj) // 二者之間是否是同一個對象?: false
    console.log('innerObj:', innerObj) // innerObj: { name: '2' }
    console.log('_innerObj: ', _innerObj) // _innerObj:  { name: '1' }
}

var outerObj = {};
setName(outerObj);
console.log('最終結果outerObj:', outerObj) // 最終結果outerObj: { name: '1' }

過程當中能夠看出在函數中間 innerObj = {} 以後;對象的指向就已經變了,也就是說這裏至關於從新創建一個新的指向,後續的操做都是基於新指向之上進行的。
此時,outerObj === _innerObj !== innerObj, 因此最終輸出的是1而不是2.

若是還有些混亂的同窗,看看若是不經過函數直接修改會是什麼結果?

var obj = {'a':1}
obj = {};
obj = {'a':2};
console.log(obj) // { a: 2 }

此次確確實實的是輸出2了。

知識二:JS中全部函數傳參都是按值傳遞的。
相關文章
相關標籤/搜索