最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

從一道前端面試題理解JS對(duì)象存儲(chǔ)特點(diǎn)和運(yùn)算符執(zhí)行順序

 更新時(shí)間:2026年05月06日 10:31:57   作者:程序員小寒  
在JavaScript中,運(yùn)算符的優(yōu)先級(jí)和結(jié)合性決定了它們的執(zhí)行順序,優(yōu)先級(jí)高的運(yùn)算符會(huì)先執(zhí)行,而具有相同優(yōu)先級(jí)的運(yùn)算符則按照結(jié)合性的規(guī)則決定先后順序,這篇文章主要介紹了如何從一道前端面試題理解JS對(duì)象存儲(chǔ)特點(diǎn)和運(yùn)算符執(zhí)行順序的相關(guān)資料,需要的朋友可以參考下

本文大綱

今天來看一道前端面試的代碼輸出題。

面試官提供了一段 Javascript 代碼,要求給出這段代碼運(yùn)行后的輸出結(jié)果。

const obj = {
  a: 0,
};

obj['1'] = 0;
obj[++obj.a] = obj.a++;
const values = Object.values(obj);
obj[values[1]] = obj.a;
console.log(obj);

先分析這道題前,先補(bǔ)充兩個(gè)個(gè)前置知識(shí)點(diǎn)。

知識(shí)點(diǎn)一:對(duì)象的常規(guī)屬性 (properties) 和排序?qū)傩?(elements)

先來看下面一段代碼:

const obj = {};
obj['b'] = 'b'
obj[100] = '100';
obj[1] = '1';
obj['a'] = 'a';
obj[50] = '50';
obj['c'] = 'c';

for (const key in obj){ 
  console.log(`key: ${key} value: ${obj[key]}`)
}
/**
 * 打印結(jié)果如下:
  key: 1 value: 1
  key: 50 value: 50
  key: 100 value: 100
  key: b value: b
  key: a value: a
  key: c value: c
 */

觀察下打印的數(shù)據(jù),很明顯屬性的設(shè)置順序并不是打印的順序,比如 b 屬性是第一個(gè)設(shè)置的,打印結(jié)果卻排在 100 后面,仔細(xì)分析他們的打印規(guī)律,可以得到如下特點(diǎn):

  1. 數(shù)字類的屬性不管設(shè)置的順序先后,都會(huì)被優(yōu)先打印,而且是按照從小到大的升序進(jìn)行打印的。
  2. 字符類屬性會(huì)按照設(shè)置的順序進(jìn)行打印,上面我們是按照 b、ac 的順序進(jìn)行設(shè)置的,打印順序也是如此。

為什么會(huì)出現(xiàn)這樣的結(jié)果呢?

這是因?yàn)?ECMAScript 規(guī)范中定義了數(shù)字屬性應(yīng)該按照索引值大小升序排列,字符串屬性根據(jù)創(chuàng)建時(shí)的順序升序排列。在 V8 中數(shù)字屬性被稱為 elements,字符串屬性被稱為 properties。之所以這樣設(shè)置,主要是為了提升訪問性能。elements 對(duì)象中會(huì)按照順序存放數(shù)字屬性,類似于數(shù)組的存儲(chǔ),這樣查詢的效率當(dāng)然就很高了。

知識(shí)點(diǎn)二:JavaScript 運(yùn)算符的執(zhí)行順序

JavaScript 中最常見運(yùn)算符如下(運(yùn)算順序從高到低排列):

  • 對(duì)象屬性訪問,比如 obj.a,obj['a']
  • 遞增/遞減,比如 a++(后置遞增) 或 ++a(前置遞增)。
  • 算術(shù),比如 a + 1。
  • 比較,包括 <(小于)、>(大于)、<=(小于等于)、>=(大于等于),比如 a > 3
  • 相等,包括 == 粗略相等, ===嚴(yán)格相等,!== 粗略不等,!== 嚴(yán)格不等,比如 a == 1。
  • 邏輯,也就是與或非,&(與)、|(或)、!(非),比如 a && b
  • 三元,比如 flag ? '1' : '0'。
  • 賦值,比如 a = 1。

對(duì)于單個(gè)賦值語(yǔ)句 LHS = RHS 的求值,根據(jù) ECMAScript 規(guī)范(ECMA-262, AssignmentExpression evaluation),對(duì)于 LeftHandSideExpression = AssignmentExpression,其計(jì)算順序如下:

  • 第一步,先得到一個(gè) 引用(Reference),即“要寫入的位置”,也就是 Evaluate LeftHandSideExpression。
  • 第二步,再計(jì)算右側(cè)的值,Evaluate AssignmentExpression
  • 最后將第二步得到的值寫入第一步的引用當(dāng)中。

也就是說,對(duì)于LHS = RHS 這樣的賦值表達(dá)式,其計(jì)算順序是左側(cè)先求值(為了知道寫到哪),右側(cè)后求值(為了知道寫什么),最后將右側(cè)的值寫入左側(cè)。

?? 注意:這里說的“左側(cè)求值”不是求它的值,而是求它的“位置”(比如屬性名、變量名等)。例如對(duì)于 obj[++obj.a],要確定屬性名,就必須先執(zhí)行 ++obj.a

寫個(gè)簡(jiǎn)單例子:

const obj = {
  get a() {
    console.log('獲取 a 的值');
    return 1;
  },
  get b() {
    console.log('獲取 b 的值');
    return 2;
  }
}
obj[++obj.a] = obj.b++;
console.log('obj: ', obj);

我們前面說過,運(yùn)算符順序是對(duì)象屬性訪問 > 遞增/遞減 > 賦值,對(duì)于賦值運(yùn)算符 LHS = RHS,會(huì)先求出左側(cè) LHS引用(Reference),再計(jì)算右側(cè) RHS 的值,最后將右側(cè)的值賦值給左側(cè)的引用。所以用這個(gè)邏輯來分析下這段代碼的執(zhí)行順序:

  • 第一步,先取 obj.a 的值, 取到的值為 1, 然后執(zhí)行前置遞增 ++obj.a,結(jié)果為 2,然后程序就知道要往 obj2 屬性上賦值了。
  • 第二步,然后再取 obj.b 的值,執(zhí)行后置遞增 obj.b++,右側(cè)計(jì)算的值為 2。
  • 最后把右側(cè)計(jì)算的結(jié)果值 2 賦值給 obj[2] 屬性。

逐行分析代碼執(zhí)行過程

了解了這兩個(gè)知識(shí)點(diǎn)后,讓我們來逐行解析下這段代碼。

const obj = {
  a: 0,
};

obj['1'] = 0;
obj[++obj.a] = obj.a++;
const values = Object.values(obj);
obj[values[1]] = obj.a;
console.log(obj);
  1. 首先,我們定義了一個(gè)對(duì)象 obj,它有一個(gè)屬性 a,值為 0。
const obj = {
  a: 0,
};
  1. 接下來,我們給 obj 添加了一個(gè)屬性 1,值為 0,此時(shí)對(duì)象中有兩個(gè)屬性,a1。
obj['1'] = 0;

由于數(shù)字屬性會(huì)排在前面,此時(shí) obj 的值為:

{
  "1": 0,
  "a": 0,
}
  1. 然后會(huì)執(zhí)行 obj[++obj.a] = obj.a++,前面我們分析過運(yùn)算符的優(yōu)先級(jí),先執(zhí)行左側(cè) ++obj.a 得到 1,然后執(zhí)行右側(cè) obj.a++, 由于是后置遞增,所以右側(cè)的值為 1,執(zhí)行賦值后,obj 的值為:
{
  "1": 1,
  "a": 2,
}
  1. 經(jīng)過 Object.values(obj) 后,values 的值為 [1, 2]。
  2. 執(zhí)行 obj[values[1]] = obj.a ,轉(zhuǎn)換后就是 obj[2] = 2。obj 的值變?yōu)椋?/li>
{
  "1": 1,
  "2": 2,
  "a": 2,
}

這就是最終的輸出結(jié)果了。

小結(jié)

該題主要考察兩個(gè)知識(shí)點(diǎn):

  1. JavaScript 對(duì)象中,屬性的設(shè)置順序并不一定是循環(huán)打印順序,在 V8中,數(shù)字類的屬性在被稱為 elements(按從小到大排列存儲(chǔ)),字符類屬性被稱為 properties(按添加順序存儲(chǔ))。
  2. JavaScript 運(yùn)算符的運(yùn)算順序是對(duì)象屬性訪問 > 遞增/遞減 > 賦值,對(duì)于賦值運(yùn)算符 LHS = RHS,會(huì)先求出左側(cè) LHS引用(Reference),再計(jì)算右側(cè) RHS 的值,最后將右側(cè)的值賦值給左側(cè)的引用。

到此這篇關(guān)于從JS對(duì)象存儲(chǔ)特點(diǎn)和運(yùn)算符執(zhí)行順序的文章就介紹到這了,更多相關(guān)JS對(duì)象存儲(chǔ)和運(yùn)算符執(zhí)行順序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

黑河市| 平武县| 萨迦县| 隆德县| 额济纳旗| 镇宁| 城市| 平凉市| 四平市| 大英县| 浑源县| 西贡区| 阜宁县| 农安县| 宝山区| 通辽市| 大石桥市| 盐山县| 乌兰察布市| 翁源县| 通道| 大同县| 石景山区| 尉氏县| 延吉市| 青龙| 成武县| 武川县| 泰和县| 上饶县| 封开县| 楚雄市| 苍山县| 秭归县| 寻甸| 丽水市| 黔江区| 从江县| 隆回县| 铜鼓县| 冷水江市|