一文帶你深入理解JavaScript對象與包裝類
對象的創(chuàng)建方式
- 對象字面量:最直接的方式,通過鍵值對的形式定義對象。
var mrPeng = { name: '彭于晏', age: 18, sex: 'boy', };
new Object()
:構(gòu)造函數(shù)方式創(chuàng)建一個空對象。
var obj = new Object();
- 自定義構(gòu)造函數(shù):通過
new
關(guān)鍵字調(diào)用自定義的構(gòu)造函數(shù)來創(chuàng)建特定類型的對象。
function Car(name, height) { this.name = name; this.height = height; } var car = new Car('Toyota', 1500);
- 模擬構(gòu)造函數(shù):模擬一個構(gòu)造函數(shù),但不使用
new
關(guān)鍵字,需手動實現(xiàn)。
function Person(name, age){ var self = {}; self.name = name; self.age = age; return self; } let p = Person('Alice', 30);
包裝類
進度一
先來看看這段JS代碼:
var num = 123; num.a = 'aaa'; console.log(num.a); // undefined
簡單解釋一下代碼:代碼中先聲明了一個Num
,并賦值為123
,再在Num
上掛上一個屬性a
,其值為字符串aaa
,然后打印輸出Num
中a
的值
如果你也是這樣想的話,那么你心中輸出的結(jié)果不就是字符串aaa
嘛??墒禽敵龅慕Y(jié)果真的是字符串aaa
嗎???
當(dāng)然不是,我可以清楚的告訴你,該段代碼輸出的是undefined
。說明屬性a
并沒有掛在num
上,畢竟num不是對象,那竟然沒掛上去,訪問不存在的東西時,不應(yīng)該報錯嗎?那又為什么輸出的是undefined
呢?
首先,我們通過該段代碼能知道:在JS中原始值(原始類型數(shù)據(jù))(如數(shù)字
Number
、字符串String
、布爾值boolean
等)不能擁有屬性和方法,屬性和方法只有對象才能擁有。
那么如果我們將var num = 123;
改寫成var num = new Number(123);
呢,我們就得到了一個對象,可是對象里面沒有key
,只有一個值為123
。展開Number(123)
這個對象看一下,就會看到有一個[[PrimitiveValue]]:123
,意思就是說這是一種特殊的對象Number(123)
,這個對象就是我們說的包裝類。
你說他是對象他就是對象,你說他是數(shù)字他也是數(shù)字,他能當(dāng)成數(shù)字來用。
var num = new Number(123); console.log(num*2);// 輸出246 num.a = 'aaa'; console.log(num.a); //輸出aaa
這就說明當(dāng)你將他用來當(dāng)對象,他就是對象,用來當(dāng)數(shù)字,他就是數(shù)字。
var num = 123;
這種創(chuàng)建的叫數(shù)字字面量,而var num = new Number(123);
創(chuàng)建的叫Number對象(數(shù)字對象)。對象是可以有屬性和方法的,而原始值是沒有的。
進度二
讓我們來看看先這段代碼:
var str ='asdf' console.log(str.length) //輸出4
為什么這個能輸出4呢?總不能說剛剛得到的結(jié)論是錯的吧
在解決上面這個問題前先來看看這段代碼:
var num = 4; num.len = 3; // console.log(num.len); // undefined
根據(jù)上面的結(jié)論,我們能知道這里的 len
是不能掛在原始值上的,輸出的肯定是undefined
,沒錯吧。
我們來解析一下上面那段代碼,看看在v8引擎是怎樣實現(xiàn)的:
- 首先,在執(zhí)行
var num = 4;
時 ,v8會將代碼執(zhí)行為new Number(4)
,也就是所有的字面量都會執(zhí)行成這個樣子,包括字符串和布爾會執(zhí)行成new String()
和new Boolean()
,將其轉(zhuǎn)換為對象,也就是包裝類。 - 然后,v8在執(zhí)行這個代碼
num.len = 3;
時,就會將len屬性掛在Number
這個對象上,且值為3。因為在JS中數(shù)字對象就是為了彌補數(shù)字字面量的不足,在JS中萬物皆對象,所有的東西都要往對象上靠 - 最后,在執(zhí)行
console.log(num.len);
之前就會突然醒悟過來,也就是在讀取該值或在執(zhí)行前會使用 str.valueof()方法 ,判斷這個對象(數(shù)字對象)是否能轉(zhuǎn)化為原始值(str.valueof()方法只能操作包裝類),如果能轉(zhuǎn)化為原始值,那么就會將屬性和方法移除,執(zhí)行delete num.len
。然而在輸出的時候,num.len
先在Number
對象中查找,找不到就會聲明一個len
屬性再對象中,但是沒有值啊,所以輸出的就是undefined
,而不不是報錯!??!
訪問對象不存在的屬性,會返回undefined
訪問不存在的不變量,會報錯!!
那么現(xiàn)在我們來解決上面那個問題:
var str ='asdf' console.log(str.length) //輸出4
- 首先,一樣的,在執(zhí)行
var str ='asdf'
時,v8會執(zhí)行為var str =new String('asdfg')
包裝類 - 然后,str調(diào)用length方法,并且輸出,他沒有往原始值上掛屬性,直接調(diào)用的話,會去對象(包裝類)中查找該方法,找不到該方法就會去,該對象的原型上找,也就是我們之前提到的,按照他的原型鏈去查找該方法,而String這個構(gòu)造函數(shù)中是有該方法的,可以直接調(diào)用。
總結(jié)
包裝類(
String
,Number
,Boolean
)是JavaScript為原始值提供的對象包裝器,允許我們像操作對象一樣操作原始值,包括訪問屬性和方法,只不過屬性和方法并不是原始值身上的,而是String
,Number
,Boolean
的構(gòu)造函數(shù)(對象)上的。原始值是不能擁有屬性和方法,屬性和方法只有對象才能擁有
重要特性:每當(dāng)試圖訪問原始值的屬性或方法時,JavaScript會自動創(chuàng)建包裝類,執(zhí)行完畢后立即銷毀,確保原始值的不變性。這就是為什么直接給原始值添加屬性沒有效果的原因。
valueOf()
:為了使valueOf
在類型轉(zhuǎn)換過程中有用,它必須返回一個原始值(基本類型值)。所有的原始類型(基本類型)都有自己的valueOf()
方法。JavaScript 調(diào)用valueOf
方法來將對象轉(zhuǎn)換成原始值(基本類型值)。你很少需要自己調(diào)用valueOf
方法;當(dāng)遇到需要基本類型值的對象時,JavaScript 會自動的調(diào)用該方法。原始值對象,v8 執(zhí)行到包裝類時,會通過
valueOf()
試探該包裝類是不是原始值,如果是,則秉承原始值不用具有屬性和方法的這一規(guī)則,再移除掉給包裝類添加的屬性
以上就是深入理解JavaScript對象與包裝類的詳細內(nèi)容,更多關(guān)于JavaScript對象與包裝類的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
echarts自定義tooltip中的內(nèi)容代碼示例
在ECharts中,通過formatter函數(shù)自定義圖例樣式,可以實現(xiàn)更靈活的圖表展示,滿足特定的視覺需求,這篇文章主要介紹了echarts自定義tooltip中內(nèi)容的相關(guān)資料,需要的朋友可以參考下2024-10-10Vuejs通過拖動改變元素寬度實現(xiàn)自適應(yīng)
這篇文章主要介紹了Vuejs通過拖動改變元素寬度實現(xiàn)自適應(yīng),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-09-09javascript 產(chǎn)生隨機數(shù)的幾種方法總結(jié)
這篇文章主要介紹了javascript 產(chǎn)生隨機數(shù)的幾種方法總結(jié)的相關(guān)資料,希望通過本文大家能夠掌握如何實現(xiàn)這樣的方法,需要的朋友可以參考下2017-09-09JavaScript通如何過RGraph實現(xiàn)動態(tài)儀表盤
這篇文章主要介紹了JavaScript通如何過RGraph實現(xiàn)動態(tài)儀表盤,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-10-10