首頁 >web前端 >js教程 >JS 基本型別與參考型別值

JS 基本型別與參考型別值

Guanhui
Guanhui轉載
2020-05-28 10:30:441950瀏覽

JS 基本型別與參考型別值

引入概念:基本型別與引用型別

1、可以感受到,JS 的變數及其鬆散,那麼,正是JS 變數鬆散的本質,決定了:JS 變數名稱只是一個在特定的時間用於保存特定值的一個名字而已,也就是說,變數的值及其資料類型可以在腳本的生命週期內改變,儘管這個功能看起來有趣、強大,但JS 變數其實比較複雜。

2、ECMAScirpt 變數有兩種不同的資料型別:基本型別和引用型別,另外還有其他的叫法,例如:原始型別和物件型別、擁有方法的型別和不能擁有方法的型別等/0

3、將一個值賦值給變數時,解析器必須確定這個值是基本型別值還是引用型別值

基本型別指的是簡單的資料段,而引用類型指的是可能由多個值構成的物件

基本型別:undefined、null、string、number、boolean、symbo(ES6)

參考型別:Object、Array、RegExp 、Date、Function

兩種類型的區別

儲存:

基本類型的值是存放在堆疊區的,也就是記憶體中的堆疊記憶體

假如有下列變數:

var name = 'jozo';
var city = 'guangzhou';
var age = 22;

那麼他們的儲存結構如下:(堆疊區包含了變數的識別碼和值)

JS 基本型別與參考型別值

引用型別的值是同時保存在堆疊記憶體和堆疊記憶體的

假如有以下物件:

var person1 = {name:'jozo'};
var person2 = {name:'xiaom'};
var person3 = {name:'xiaoq'};

那麼他們的儲存結構如下:

JS 基本型別與參考型別值

存取:

基本類型的值是按值存取的,因為可以操作保存在變數中的實際的值。

引用類型的值是按引用存取的,因為引用類型的值是保存在記憶體中的對象,而與其他語言不同的是,JavaScript 不允許直接存取記憶體中的位置,即不可以直接操作物件的記憶體空間,那麼,在操作物件時,實際上是在操作物件的參考而不是實際的物件。

動態的屬性:

對於引用類型的值,很明顯,我們可以為其新增、變更、刪除屬性和方法:

var person = new Object();
person.name = "Ozzie";
console.log(person.name);    //"Ozzie"

在上述過程中,我們創建了一個物件並為其添加了一個屬性,如果物件不被銷毀或這個屬性不被刪除,那麼這個屬性將一直存在

但是,我們不可以為基本類型的值添加方法和屬性

var name = "Ozzie";
name.age = 19;
consoe.log(name.age);    //undefined

儘管這樣操作不會報錯,但是仍然會被默默地掛掉

比較:

基本類型的比較是值的比較:

例如:

var a = 1;

var b = true;

console.log(a == b);    //true

#引用型別的比較是引用的比較:

例如:

var person1 = {};
var person2 = {};
console.log(person1 == person2);    //false

上文提到過,引用型別時按引用存取的,換句話說就是比較兩個物件的堆記憶體中的位址是否相同,很明顯,並不是同一個記憶體位置:

JS 基本型別與參考型別值

複製變數值:

將一個基本類型的值複製給另一個變量,那麼,會在新變量上創建一個新值,然後再把該值複製到為新變量分配的位置上:

例如:

var a = 10;
var b = a;
a++;
console.log(a);    // 11
console.log(b);    // 10

a 與b 是完全獨立的,該值只是a 中的值的副本。

基本型別在賦值運算後,兩個變數是互相不受影響的:

JS 基本型別與參考型別值

#那麼,複製引用型別的值時,同樣也會將一份儲存在物件中的值複製到新變數的空間中,不同的是,這個值的副本其實是一個指針,指向的是儲存在堆中的物件。也就是說,複製結束後,這兩個變數將引用同一個物件。

例如:

var a = {}; // a保存了一个空对象的实例
var b = a;  // a和b都指向了这个空对象
a.name = 'jozo';
console.log(a.name); // 'jozo'
console.log(b.name); // 'jozo'

改變其中一個變數就會影響到另一個變數

JS 基本型別與參考型別值

傳遞參數:

#######請記住,儘管在存取變數時有著按值存取和按引用存取這兩種方式,但ECMAScript 中所有的函數的參數都是按值傳遞的,即參數只能按值傳遞,也就是說,把函數外部的值複製給函數內部的參數,就類似於變數之間的值複製一樣######基本類型的值的傳遞如同基本類型的變數的複製,被傳遞的值會被賦值給一個局部變數(即命名參數,用ECMAScript 中的概念說,就是arguments 物件中的一個元素),此處不再贅述…###

但是向参数传递引用类型的值时,复制给局部变量的是 内存中的地址,因此这个局部变量的变化会被反映在函数的外部。

例如:

function setName(obj){
      obj.name = "Ozzie";
}
var person = new Object();
setName(person);
console.log(person.name);    //"Ozzie"

我们可以看到,在函数内部,obj 和 person 引用的是同一个对象,换句话说,即使这个变量是按值传递的,obj 也会按引用来访问同一个对象,因为 person 指向的对象在堆内存中只有一个,而且是全局对象。

很多人会 错误地认为:参数是按引用传递的,因为在局部作用域中修改的参数会在全局作用域中反映出来,OK,那么我们再看一个例子:

function setName(obj){
      obj.name = "Ozzie";
      obj = new Object();
      obj.name = "Nicholas"
}
var person = new Object();
setName(person);
console.log(person.name);    //Ozzie

如果是按引用传递参数的,那么显然 person 对象就会在函数内部自动修改 name 属性为 Nicholas,但结果仍然是 Ozzie,这说明,即使在函数内部修改了参数的值,但原始的引用仍然保持不变,实际上,在函数内部重写 obj 时,这个变量的引用就是一个局部对象了,而这个局部对象在函数执行完毕后立即被销毁。

推荐教程:《PHP教程

以上是JS 基本型別與參考型別值的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:learnku.com。如有侵權,請聯絡admin@php.cn刪除