亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

數(shù)值類型vs引用類型

missonce / 3262人閱讀

摘要:數(shù)值類型引用類型有種通過(guò)復(fù)制數(shù)值傳值的數(shù)據(jù)類型。我們稱之為原始基本數(shù)據(jù)類型還有三種通過(guò)引用傳值的數(shù)據(jù)類型。當(dāng)?shù)仁竭\(yùn)算符和用于引用型變量時(shí),他們會(huì)檢查引用。這是中的地方在內(nèi)存中的映射包含了函數(shù)的引用,其他變量則包含基本數(shù)據(jù)類型的數(shù)據(jù)。

本文旨在了解如何復(fù)制對(duì)象、數(shù)組和函數(shù)以及如何將它們傳遞到函數(shù)中。知道引用類型復(fù)制的是什么。了解原始值是通過(guò)復(fù)制值來(lái)復(fù)制及傳遞的。

數(shù)值類型 & 引用類型

JavaScript有5種通過(guò)復(fù)制數(shù)值傳值的數(shù)據(jù)類型:Boolean, null, undefined, String, and Number。我們稱之為原始/基本數(shù)據(jù)類型
JavaScript還有三種通過(guò)引用傳值的數(shù)據(jù)類型:Array, Function, and Object。從專業(yè)角度講,它們都是Objects, 故而統(tǒng)稱為對(duì)象。

原始/基本數(shù)據(jù)類型

若為一個(gè)基本數(shù)據(jù)類型的變量賦值,我們可以認(rèn)為變量包含了這個(gè)原始值。

var x = 10;
var y = "abc";
var z = null;

這張圖形象的展示了變量在內(nèi)存中的存儲(chǔ)情況:

Variables Values
x 10
y "abc"
z null

當(dāng)我們用 = 將這些變量賦值給其他變量時(shí),我們把這些值拷貝給了這些新變量。他們通過(guò)值復(fù)制的。

var x = 10;
var y = "abc";

var a = x;
var b = y;

console.log(x, y, a, b);
// -> 10, "abc", 10, "abc"

ax 現(xiàn)在的值都是10. by 都擁有值 "abc"。他們各自獨(dú)立,擁有相同的值,互不影響:

Variables Values
x 10
y "abc"
a 10
b "abc"

改變其中一個(gè)值并不會(huì)影響另一個(gè)的值,彼此井水不犯河水,盡管后者曾經(jīng)復(fù)制與它:

var x = 10;
var y = "abc";

var a = x;
var b = y;

x = 5;
y= "def";

console.log(x, y, a, b); // -> 5 "def" 10 "abc"
對(duì)象

非基本數(shù)據(jù)類型的變量會(huì)保存對(duì)值的引用(地址)。該引用指向內(nèi)存中對(duì)象的地址,變量實(shí)際不包含該實(shí)際值。
對(duì)象創(chuàng)建于計(jì)算機(jī)內(nèi)存中。當(dāng)我們寫(xiě)代碼 arr = [], 我們?cè)趦?nèi)存中創(chuàng)建了一個(gè)新數(shù)組, arr 中現(xiàn)在包含了新數(shù)組在內(nèi)存中的地址。
假設(shè)address(地址)是一種新的傳遞數(shù)據(jù)的數(shù)據(jù)類型,就像數(shù)字和字符串。address指向通過(guò)引用傳遞的值的內(nèi)存地址,就像字符串由""""表示, address<> 表示。
當(dāng)我們賦值引用一個(gè)引用型變量時(shí),我們通常這樣書(shū)寫(xiě)代碼:

var arr = [];
arr.push(1);

兩步的操作分別是:
1.

Variables Values Address Objects
arr <#001> #001 []

2.

Variables Values Address Objects
arr <#001> #001 [1]

值,地址以及 變量 arr 的包含的值 是靜態(tài)不變的,僅僅是內(nèi)存中的數(shù)組改變了。當(dāng)我們對(duì)arr 進(jìn)行操作時(shí),例如添加新元素, JavaScript引擎會(huì)獲取 arr 在內(nèi)存中的地址 并操作該地址存儲(chǔ)的數(shù)據(jù)。

引用賦值

當(dāng)一個(gè)引用型值即對(duì)象被用 = 賦值給另一個(gè)變量, 實(shí)際上復(fù)制過(guò)去的是那個(gè)引用型值的地址。對(duì)象通過(guò)引用賦值而不是直接傳值。對(duì)象本身是靜態(tài)不變的,唯一改變的 是對(duì)象的 引用 、地址。

var reference = [1];
var refCopy = reference;

內(nèi)存變化:

Variables Values Address Objects
reference <#001> #001 [1]
refCopy <#001>

現(xiàn)在每個(gè)變量都包含了同一個(gè)數(shù)組的引用,它們地址相同,這意味著如果我們改變了這個(gè)引用即改變referencerefCopy 也會(huì)隨之改變,這一點(diǎn)與基本數(shù)據(jù)類型的值不一樣。

reference.push(2);
console.log(reference, refCopy);
// -> [1, 2], [1, 2]
Variables Values Address Objects
reference <#001> #001 [1,2]
refCopy <#001> [1,2]
重新賦值 :

重新復(fù)制會(huì)覆蓋舊值:

var obj = { first: "reference" };

內(nèi)存變化:

Variables Values Address Objects
obj <#234> #234 { first: "reference" }

重新賦值:

var obj = { first: "reference" };
obj = { second: "ref2" }

Address存儲(chǔ)了 obj 的變化 ,第一個(gè)對(duì)象仍在內(nèi)存,第二個(gè)對(duì)象也在:

Variables Values Address Objects
obj <#678> #234 { first: "reference" }
#678 { second: "ref2" }

當(dāng)已經(jīng)存在的對(duì)象沒(méi)有被引用時(shí),如上邊的 #234 ,JavaScript會(huì)啟動(dòng)垃圾回收機(jī)制。這就意味著程序員失去了對(duì)該對(duì)象的所有引用,不能再使用這個(gè)對(duì)象,所以JavaScript可以安全地刪除它。 這時(shí),對(duì)象 { first: "reference" } 不能再被任何變量獲取,內(nèi)存會(huì)被回收。

== and ===

當(dāng) 等式運(yùn)算符 ===== 用于引用型變量時(shí), 他們會(huì)檢查引用。 如果多個(gè)變量包含同一項(xiàng)目的引用時(shí), 結(jié)果會(huì)返回 true

var arrRef = ["Hi!"];
var arrRef2 = arrRef;

console.log(arrRef === arrRef2); // -> true

如果他們是不同的對(duì)象,即使它們包含相同的內(nèi)容, 比較結(jié)果也會(huì)返回 false

var arr1 = ["Hi!"];
var arr2 = ["Hi!"];

console.log(arr1 === arr2); // -> false
對(duì)象的比較

如果想比較兩個(gè)對(duì)象的屬性是否一樣,比較運(yùn)算符會(huì)失去作用。我們必須編一個(gè)函數(shù)來(lái)檢查對(duì)象的每一條屬性和值是否相同。對(duì)于兩個(gè)數(shù)組,我們需要一個(gè)函數(shù)遍歷數(shù)組每項(xiàng)檢查是否相同。

函數(shù)傳參

當(dāng)我們傳遞基本數(shù)據(jù)類型的值給一個(gè)函數(shù)時(shí),函數(shù)拷貝這個(gè)值作為自己的參數(shù)。效果和 = 相同:

var hundred = 100;
var two = 2;

function multiply(x, y) {
    // PAUSE
    return x * y;
}

var twoHundred = multiply(hundred, two);

上例中,我們將 hundred 賦值 100 。當(dāng)我們把他傳遞給 multiply, 變量x 獲得值 100 。如果用 = 賦值,值會(huì)被復(fù)制。 而且,hundred的值不會(huì)被影響。 這是multiply//的地方在內(nèi)存中的映射:

Variables Values Address Objects
hundred 100 #333 function(x, y) {… }
two 2
multiply <#333>
x 100
y 2
twoHundred undefined

multiply包含了函數(shù)的引用,其他變量則包含基本數(shù)據(jù)類型的數(shù)據(jù)。
twoHundredundefined 因?yàn)槲覀冞€沒(méi)有函數(shù)返回結(jié)果,在函數(shù)返回結(jié)果前,它等于
undefined

純函數(shù)

純函數(shù)是指不影響外部作用域的函數(shù)。只要一個(gè)函數(shù)只接受基本數(shù)據(jù)類型的值作為參數(shù)并且不適用任何外部范圍的變量,他就是純函數(shù)不會(huì)污染外部作用域。所有純函數(shù)的變量在函數(shù)返回結(jié)果后會(huì)進(jìn)入JavaScript的垃圾回收機(jī)制。
然而,接受一個(gè)對(duì)象(作為參數(shù))的函數(shù)會(huì)改變他周圍作用域的狀態(tài)。如果函數(shù)接受一個(gè)數(shù)組的引用并改變了它指向的數(shù)組,可能是添加元素,引用這個(gè)數(shù)組的外部變量會(huì)見(jiàn)證這些變化。當(dāng)函數(shù)返回結(jié)果后,產(chǎn)生的改變會(huì)影響外部作用域。這會(huì)導(dǎo)致很難追蹤到的負(fù)面影響。
許多本地?cái)?shù)組函數(shù)包含Array.mapArray.filter,因此都以純函數(shù)編寫(xiě)。 它們接收一個(gè)數(shù)組作為參數(shù),在內(nèi)部 它們會(huì)復(fù)制該數(shù)組操作這個(gè)副本數(shù)組而不是原數(shù)組。這使得原數(shù)組不被接觸得到,從而外部作用域不受影響,返回一個(gè)新數(shù)組的引用。
對(duì)比一下純函數(shù) 和 非純函數(shù):

function changeAgeImpure(person) {
    person.age = 25;
    return person;
}

var alex = {
    name: "Alex",
    age: 30
};

var changedAlex = changeAgeImpure(alex);

console.log(alex); // -> { name: "Alex", age: 25 }
console.log(changedAlex); // -> { name: "Alex", age: 25 }

非純函數(shù)接受了對(duì)象,改變了objectage屬性 為25,由于它對(duì)前面聲明的引用直接起作用,直接改變了alex 對(duì)象。注意當(dāng)返回person對(duì)象時(shí),它返回與傳遞的相同的對(duì)象。alexalexChanged 包含了對(duì)同一個(gè)對(duì)象的引用,既返回了person 變量又返回了有相同引用的新變量。
純函數(shù):

function changeAgePure(person) {
    var newPersonObj = JSON.parse(JSON.stringify(person));
    newPersonObj.age = 25;
    return newPersonObj;
}

var alex = {
    name: "Alex",
    age: 30
};

var alexChanged = changeAgePure(alex);

console.log(alex); // -> { name: "Alex", age: 30 }
console.log(alexChanged); // -> { name: "Alex", age: 25 }

在這個(gè)函數(shù)中,我們利用 JSON.stringify 將傳遞的對(duì)象轉(zhuǎn)化成字符串,然后用JSON.parse重新解析回一個(gè)對(duì)象。存儲(chǔ)新結(jié)果至一個(gè)新變量中,我們創(chuàng)建了一個(gè)新對(duì)象。新對(duì)象具有源對(duì)象一樣的屬性和值,唯一區(qū)別是內(nèi)存的地址的不同。
當(dāng)改變新對(duì)象的age時(shí),原對(duì)象并沒(méi)有受到影響。這個(gè)函數(shù)就是純潔純凈的。它沒(méi)有影響任何外部作用域的對(duì)象,甚至傳入函數(shù)的對(duì)象。新的對(duì)象需要被返回 并將其存儲(chǔ)在一個(gè)新變量中否則一旦函數(shù)執(zhí)行完畢就會(huì)被回收,該對(duì)象在作用于內(nèi)就再也找不到了。
以下幾個(gè)例子看看你是否理解了上述內(nèi)容:

function changeAgeAndReference(person) {
    person.age = 25;
    person = {
      name: "John",
      age: 50
    };

    return person;
}

var personObj1 = {
    name: "Alex",
    age: 30
};

var personObj2 = changeAgeAndReference(personObj1);

console.log(personObj1); // -> { name: "Alex", age: 25 }
console.log(personObj2); // -> { name: "John", age: 50 }

解析:
上述函數(shù) 等于:

var personObj1 = {
    name: "Alex",
    age: 30
};

var person = personObj1;
person.age = 25;

person = {
    name: "John",
    age: 50
};

var personObj2 = person;

console.log(personObj1); // -> { name: "Alex", age: 25 }
console.log(personObj2); // -> { name: "John", age: 50 }

唯一一點(diǎn)不同是前者person在函數(shù)結(jié)束后就被回收了。

再來(lái)幾道題:

// 1
var obj = {
    innerObj: {
        x: 9
    }
};

var z = obj.innerObj;

z.x = 25;

console.log(obj.innerObj.x);

// 2
var obj = {
    arr: [{ x: 17 }]
};

var z = obj.arr;

z = [{ x: 25 }];

console.log(obj.arr[0].x);

//  3
var obj = {};
var arr = [];
obj.arr = arr;
arr.push(9);
obj.arr[0] = 17;

console.log(obj.arr === [17]);

//    4
function fn(item1, item2) {
    if (item2 === undefined) {
        item2 = [];
    }
    
    item2[0] = item1;
    
    return item2;
}
?
var w = {};
var x = [w];
var y = fn(w);
var z = fn(w, x);
?
console.log(x === y);

結(jié)果:

25

17

false

false

3和4 需要注意一點(diǎn): [5] === [5] ====> false

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/89701.html

相關(guān)文章

  • javascript -- == vs ===

    摘要:判斷一個(gè)值是否是,只能用來(lái)判斷如果兩個(gè)都是字符串,每個(gè)位置的字符都一樣,那么相等否則不相等。如果一個(gè)是字符串,一個(gè)是數(shù)值,把字符串轉(zhuǎn)換成數(shù)值再進(jìn)行比較。對(duì)象轉(zhuǎn)換成基礎(chǔ)類型,利用它的或者方法。核心內(nèi)置類,會(huì)嘗試先于例外的是,利用的是轉(zhuǎn)換。 javascript-- == vs === 高級(jí)語(yǔ)言層出不窮, 各個(gè)語(yǔ)言雖說(shuō)思想一致,但仍有各自獨(dú)特的設(shè)計(jì)理念和語(yǔ)法, js有許多容易讓人迷惑的地方...

    BothEyes1993 評(píng)論0 收藏0
  • javascript的深拷貝VS淺拷貝

    摘要:深拷貝淺拷貝本文主要對(duì)深拷貝淺拷貝的解釋及實(shí)現(xiàn)做一下簡(jiǎn)單記錄。之所以會(huì)有深拷貝與淺拷貝之分,是因?yàn)椴煌瑪?shù)據(jù)類型的數(shù)據(jù)在內(nèi)存中的存儲(chǔ)區(qū)域不一樣。但注意,只能做一層屬性的淺拷貝。 深拷貝VS淺拷貝 本文主要對(duì)深拷貝&淺拷貝的解釋及實(shí)現(xiàn)做一下簡(jiǎn)單記錄。原文鏈接,歡迎star。 之所以會(huì)有深拷貝與淺拷貝之分,是因?yàn)椴煌瑪?shù)據(jù)類型的數(shù)據(jù)在內(nèi)存中的存儲(chǔ)區(qū)域不一樣。 堆和棧是計(jì)算機(jī)中劃分出來(lái)用來(lái)存儲(chǔ)的...

    Nekron 評(píng)論0 收藏0
  • 復(fù)習(xí)Javascript專題(一):基本概念部分

    摘要:一數(shù)據(jù)類型基本類型引用類型類型判斷返回結(jié)果未定義布爾值字符串?dāng)?shù)值對(duì)象或者函數(shù)拓展堆棧兩種數(shù)據(jù)結(jié)構(gòu)堆隊(duì)列優(yōu)先,先進(jìn)先出由操作系統(tǒng)自動(dòng)分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等。 一、數(shù)據(jù)類型 基本類型:`Null Boolean String Undefined Number(NB SUN)` 引用類型:`Array Function Object` 類型判斷:typeof 返回結(jié)果...

    LiangJ 評(píng)論0 收藏0
  • 引用傳遞和值傳遞(pass by value vs pass by reference)

    摘要:字節(jié)碼驗(yàn)證于是就寫(xiě)了以下的類,用來(lái)驗(yàn)證然后,然后,看字節(jié)碼如下圖。以上,就是整個(gè)關(guān)于引用傳遞和值傳遞的理解,有說(shuō)的不對(duì)的,望指正。 寫(xiě)這個(gè)的原因主要是今天看到了知乎的一個(gè)問(wèn)題,發(fā)現(xiàn)自己有些地方有點(diǎn)懵逼,寫(xiě)下來(lái)記錄一下,知乎上排名第一的答案說(shuō)的很清楚,不過(guò)看了以后依舊有點(diǎn)迷迷糊糊,所以自己寫(xiě)了個(gè)幾行代碼測(cè)試。首先上一個(gè),感覺(jué)比較對(duì)的結(jié)論:**Horstmann的《java核心技術(shù)》(中文...

    longmon 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<