您好,登錄后才能下訂單哦!
前言
在讀 Winter 大佬的《重學(xué)前端》欄目時(shí),重溫了 JS 的「拆箱轉(zhuǎn)換」?!秆b箱轉(zhuǎn)換」與「拆箱轉(zhuǎn)換」以前都是了解的,今天來看,自己所謂的了解也真是一知半解。在閱讀 Winter 老師寫的內(nèi)容后,對「拆箱轉(zhuǎn)換」這個(gè)知識點(diǎn)還是不甚清楚,因此我再去深入地了解一番,參考資料詳見文末的「參考鏈接」。
被我們忽略的表象
首先,我們來看一下例子:
const a = { name: 'a', toString () { console.log(this); console.log('toString'); return { name: 'toString' }; }, valueOf () { console.log(this); console.log('valueOf'); return { name: 'valueOf' }; } }; a * 2; // {name: "a", toString: ƒ, valueOf: ƒ} // valueOf // {name: "a", toString: ƒ, valueOf: ƒ} // toString // Uncaught TypeError: Cannot convert object to primitive value a + ""; // {name: "a", toString: ƒ, valueOf: ƒ} // valueOf // {name: "a", toString: ƒ, valueOf: ƒ} // toString // Uncaught TypeError: Cannot convert object to primitive alert(a); // {name: "a", toString: ƒ, valueOf: ƒ} // toString // {name: "a", toString: ƒ, valueOf: ƒ} // valueOf // Uncaught TypeError: Cannot convert object to primitive value
可以看到,toString 和 valueOf 的執(zhí)行順序并不固定,而是根據(jù)某個(gè)條件來決定的,那么是根據(jù)什么呢?那就是在拆箱轉(zhuǎn)換時(shí),調(diào)用了對象的 ToPrimitive 內(nèi)部函數(shù)時(shí),其會(huì)根據(jù)執(zhí)行上下文,自動(dòng)傳入一個(gè)轉(zhuǎn)換類型參數(shù),暫時(shí)給它命名為 hint。
ToPrimitive
在 JavaScript 標(biāo)準(zhǔn)中,規(guī)定了 ToPrimitive 函數(shù),它是對象類型到基本類型轉(zhuǎn)換的實(shí)現(xiàn)者(即,拆箱轉(zhuǎn)換);但這是一個(gè)內(nèi)部算法,是編程語言在內(nèi)部執(zhí)行時(shí)遵循的一套規(guī)則。
對象到 String 和 Number 的轉(zhuǎn)換都遵循“先拆箱再轉(zhuǎn)換”的規(guī)則。通過拆箱轉(zhuǎn)換,把對象變成基本類型,再從基本類型轉(zhuǎn)換為對應(yīng)的 String 或者 Number。
但是對于不同的操作,拆箱轉(zhuǎn)換的內(nèi)部實(shí)現(xiàn)也有所區(qū)別,正如上面的例子所示。
「拆箱轉(zhuǎn)換」的調(diào)用規(guī)則及順序如下:
來看一下第一種情況:
const b = { [Symbol.toPrimitive] (hint) { console.log(`hint: ${hint}`); return {}; }, toString () { console.log('toString'); return 1; }, valueOf () { console.log('valueOf'); return 2; } }; alert(b); // hint: string b + ''; // hint: default b + 500; // hint: default +b; // hint: number b * 1; // hint: number
第二、三種情況:
const c = { toString () { console.log('toString'); return 1; }, valueOf () { console.log('valueOf'); return 2; } }; alert(c); // 打印出 toString 并 alert 出 1 c + ''; // 先后打印出 valueOf,"2" c + 500; // 先后打印出 valueOf,502 +c; // 先后打印出 valueOf,2 c * 1; // 先后打印出 valueOf,2
那么關(guān)于 hint 可取的三種值,都有什么含義?又什么情況對應(yīng)什么值?
確定 hint 取值
string
當(dāng)在希望是字符串操作,也即發(fā)生對象到字符串的轉(zhuǎn)換時(shí),傳入內(nèi)部函數(shù) ToPrimitive 的參數(shù)值即為 string:
// output alert(obj); // using object as a property key anotherObj[obj] = 123;
number
當(dāng)在希望是數(shù)值操作,也即發(fā)生對象到數(shù)值的轉(zhuǎn)換時(shí),傳入內(nèi)部函數(shù) ToPrimitive 的參數(shù)值即為 number:
// explicit conversion let num = Number(obj); // maths (except binary plus) let n = +obj; // unary plus let delta = date1 - date2; // less/greater comparison let greater = user1 > user2;
default
當(dāng)在一些不確定需要將對象轉(zhuǎn)換成什么基礎(chǔ)類型的場景下,傳入內(nèi)部函數(shù) ToPrimitive 的參數(shù)值即為 default:
// binary plus let total = car1 + car2; // obj == string/number/symbol if (user == 1) { ... };
結(jié)語
如果親愛的讀者們在本文中發(fā)現(xiàn)了什么錯(cuò)誤,或者有什么不同的意見,還請留言,一起討論,一起將隱藏的、晦澀的點(diǎn)提出來,然后解決掉。
參考鏈接
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對億速云的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。