談談JavaScript中裝箱和拆箱

call_me_R發表於2019-06-04

JavaScript裡面有個引用型別叫做基本包裝型別,它包括String、Number和Boolean。那麼它和基本的型別String、Number和Boolean是啥關係呢?接著往下看?

裝箱操作

所謂的裝箱,是指將基本資料型別轉換為對應的引用型別的操作。而裝箱又分為隱式裝箱和顯式裝箱

隱式裝箱

對於隱式裝箱,我們看下下面的程式碼:

var s1 = 'call_me_R'; // 隱式裝箱
var s2 = s1.substring(2);
複製程式碼

上面程式碼的執行步驟其實是這樣的:

  1. 建立String型別的一個例項;
  2. 在例項中呼叫制定的方法;
  3. 銷燬這個例項。

上面的三個步驟轉換為程式碼,如下:

# 1
var s1 = new String('call_me_R');
# 2
var s2 = s1.substring(2);
# 3
s1 = null;
複製程式碼

隱式裝箱當讀取一個基本型別值時,後臺會建立一個該基本型別所對應的基本包裝型別物件。在這個基本型別的物件上呼叫方法,其實就是在這個基本型別物件上呼叫方法。這個基本型別的物件是臨時的,它只存在於方法呼叫那一行程式碼執行的瞬間,執行方法後立即被銷燬。這也是在基本型別上新增屬性和方法會不識別或報錯的原因了,如下:

var s1 = 'call_me_R';
s1.job = 'frontend engineer';
s1.sayHello = function(){
	console.log('hello kitty');
}
console.log(s1.job); // undefined
s1.sayHello(); // Uncaught TypeError: s1.sayHello is not a function
複製程式碼

顯示裝箱

裝箱的另一種方式是顯示裝箱,這個就比較好理解了,這是通過基本包裝型別物件對基本型別進行顯示裝箱,如下:

var name = new String('call_me_R');
複製程式碼

顯示裝箱的操縱可以對new出來的物件進行屬性和方法的新增啦,因為通過通過new操作符建立的引用型別的例項,在執行流離開當前作用域之前一直保留在記憶體中

var objStr = new String('call_me_R');
objStr.job = 'frontend engineer';
objStr.sayHi = function(){
	console.log('hello kitty');
}
console.log(objStr.job); // frontend engineer
objStr.sayHi(); // hello kitty
複製程式碼

拆箱操作

拆箱就和裝箱相反了。拆箱是指把引用型別轉換成基本的資料型別。通常通過引用型別的valueOf()和toString()方法來實現。

在下面的程式碼中,留意下valueOf()和toString()返回值的區別:

var objNum = new Number(64);
var objStr = new String('64');
console.log(typeof objNum); // object
console.log(typeof objStr); // object
# 拆箱
console.log(typeof objNum.valueOf()); // number 基本的數字型別,想要的
console.log(typeof objNum.toString()); // string 基本的字元型別,不想要的
console.log(typeof objStr.valueOf()); // string 基本的資料型別,不想要的
console.log(typeof objStr.toString()); // string 基本的資料型別,想要的
複製程式碼

所以,在進行拆箱操作的過程中,還得結合下實際的情況進行拆箱,別盲目來 -- 吃力不討好就很尷尬了?

後話

文章首發: github.com/reng99/blog…

更多內容:github.com/reng99/blog…

參考

JavaScript 基本型別的裝箱與拆箱

《JavaScript高階程式設計》

相關文章