JavaScript >> Javascript 文檔 >  >> Tags >> object

神秘的論據對象賦值

上週,我發現了我認為是 Firefox 的 JavaScript 實現中的一個錯誤並提交了它。 Brendan Eich 的回應表明,有問題的行為實際上符合規範,並且已經實施了一段時間。我又進行了一些測試,試圖找出我哪裡出錯了。事實上,Firefox、Internet Explorer 和 Safari 都表現出相同的行為,而 Chrome 則沒有。這就是發生的事情。

代碼

有問題的代碼如下:

function doAdd(num1, num2) {
    if(arguments.length == 1) {
        arguments[1] = 10;
    }
    alert(arguments[0] + num2);
}
doAdd(10);

您期望底線輸出什麼?在 Chrome 中,它輸出 20,因為分配給 arguments[1] 也分配給 num2 .在其他瀏覽器中,它輸出 NaN ,因為分配給 arguments[1] 也不分配給 num2 .這裡到底發生了什麼?

規範

我的困惑源於 ECMA-262 第 5 版的第 10.6 節註釋 1,內容如下:

在回答 Baranovskiy 的 JavaScript 測驗時,我之前已經討論過類似的條款,至少是第 3 版。我以為我已經理解了 arguments 總是綁定到函數的命名參數。 Tom Schuster 和 Brendan Eich 都指出,早在 10.6 節中,在創建 arguments 的說明中 對象,出現以下內容:

因此,arguments 對像是根據傳遞給函數的實際參數的數量而不是根據為函數定義的命名參數的數量創建的。這意味著,正如 Tom 指出的,將為 arguments 的數字索引創建的 setter object 僅適用於實際傳入的參數數量。因此,在我的示例中,arguments[1] 成為 arguments 的直接屬性分配 對象而不是調用將值複製到命名參數的特殊設置器。

更多代碼

因此,即使我之前的示例不適用於所有瀏覽器,但這個示例可以:

function doAdd(num1, num2) {
    arguments[1] = 10;
    alert(arguments[0] + num2);
}
doAdd(10, 25);   //20

此示例的最後一行在所有瀏覽器中輸出 20。由於我現在將兩個參數傳遞給函數,這意味著 arguments 使用兩個插槽創建對象,因此特殊設置器適用於索引 0 和 1。設置 arguments[1] 在這段代碼中實際上確實更新了 num2 並覆蓋傳入的值。

結論

規範難以理解,更難以實施。這只是一個微妙的提醒,即在 JavaScript 的黑暗角落裡有龍所在。不時戳戳龍並準確了解它們會做什麼是很有趣的。有時他們會燒死你,但無論哪種方式你都會學到。


Tutorial JavaScript 教程
  1. 使用 Puppeteer 將任何網頁變成您的個人 API

  2. 🎨 react-colorful — 1.8 KB 的 React 顏色選擇器。快速、無依賴、可定制且可訪問

  3. 我建立了我的個人網站

  4. ES6 中的生成器簡介

  5. ReactJS + Typescript + Styled-components 的可重用按鈕

  6. javascript innerHTML 添加而不是替換

  7. 為什麼 useEffect() 中的 addEventListener 和 removeEventListener 需要箭頭函數?

  1. Dispatch() 調用一個函數,但 .then() 在 React-Redux 上不起作用

  2. 上傳圖片在codeigniter 3中不起作用

  3. 我選擇加入編碼訓練營

  4. WebAssembly 與 Rust

  5. 使用 Javascript 獲取 HTML 的 DocType 作為字符串

  6. React/Webpack:從 MB 到 KB。我們如何解決捆綁問題

  7. 如何使用 Yeoman 加速啟動新項目

  1. 如何使用 Create React App 設置 ESLint、TypeScript、Prettier

  2. 你應該知道的 5 個很酷的 React 庫

  3. 從 Azure CI 管道恢復和發布 NPM 包

  4. 使用 react-query 管理應用程序緩存。以及來自 OpenAPI 的代碼生成。