摘要:背景現在最主流的模塊機制是和。模塊模塊導出的變量始終指向的是模塊內部的變量,使用時可以獲得此變量的最新值。我們叫導出綁定。但是在看對默認導出代碼的轉換時,發現實現并不使用。所以改了并不等于改了,自然的東西沒有變化。
背景
JavaScript 現在最主流的模塊機制是 commonjs 和 ES6 module。兩者不單是語法上有所區別,在加載的時候也有所不同,譬如 commonjs 是運行時加載,ES6模塊是編譯時輸出接口的。還有一個重要的區別是 commonjs 導出的東西是值拷貝,而 ES6 模塊導出的東西是……暫時認為是引用拷貝吧。具體表現出來的區別看下面的例子:
commonjs模塊// a.js var counter = 3; function incCounter() { counter++; } module.exports = { counter: counter, incCounter: incCounter, }; // main.js var mod = require("./a"); console.log(mod.counter); // 3 mod.incCounter(); console.log(mod.counter); // 3
可以看到 counter 在模塊內部被改變,但是使用此模塊的代碼獲取 counter 始終是 export 時候的值,不會變。
ES6模塊// a.js export let counter = 3; export function incCounter() { counter++; } // main.js import { counter, incCounter } from "./a"; console.log(counter); // 3 incCounter(); console.log(counter); // 4
ES6 模塊導出的變量始終指向的是模塊內部的變量,使用時可以獲得此變量的最新值。我們叫導出綁定:Exporting binding。
問題如果你去看 webpack 編譯后的實現,它會把 counter 變量轉換成 counter 的 getter,這么就可以實現綁定的效果。但是在看 webpack 對默認導出代碼的轉換時,發現實現并不使用 getter。也就是說按這種實現,使用 export default counter 是不會產生 Exporting binding。看看代碼:
// a.js let counter = 3; export function incCounter() { counter++; } export default counter; // main.js import counter, { incCounter } from "./a"; console.log(counter); // 3 incCounter(); console.log(counter); // 3解釋
為什么會有這種效果?其實 export default 是一種語法糖,當模塊只有一個導出的時候,簡化寫代碼人的代碼量,我們把這個語法糖還原下:
// 語法糖 // myFunc.js function myFunc() {} export default myFunc; // main.js import myFunc from "./myFunc"; // 非語法糖 // myFunc.js function myFunc() {} export { myFunc as default }; // main.js import { default as myFunc } from "./myFunc";
也就是說把 export 的東西重命名/賦值給 default,再在 import 的時候把 default 重命名為你想要的名字。問題就出在這層語法糖的轉換上,規范對于 export default x 的行為有解釋,x 的類型不同,則行為不同:
有名字的函數和類export default function foo() {} export default class Bar {}
相當于
function foo() {} export { foo as default }; class Bar {} export { Bar as default };沒有名字的函數和類
export default function () {} export default class {}
相當于
function *default*() {} export { *default* as default }; class *default* {} export { *default* as default };
JS會把給匿名函數或類給一個內部的變量*default*,然后再重命名為 default 導出。這個內部變量是無法通過程序獲取到的。
原始類型export default 1; // --- 或者 --- let x = 4; export default x;
相當于
let *default* = 1 export { *default* as default }; // --- 或者 --- let x = 4; let *default* = x; export { *default* as default };
當 export default x 中的 x 是沒有名字的函數或者類,又或者是原始類型,export binding 的是內部變量*default* 并不是 x。所以改了 x 并不等于改了*default*,自然 import 的東西沒有變化。
參考文獻https://2ality.com/2015/07/es...
https://stackoverflow.com/que...
https://github.com/rollup/rol...
https://ponyfoo.com/articles/...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/106869.html
摘要:當我們學習的模塊化,就會發現它的發展深受的影響。嚴格模式在模塊系統中,嚴格模式是默認開啟的。同樣的,模塊內部的聲明只在模塊內部有效。在中,我們使用導入內容在模塊中,我們只需要為導入的綁定起一個名字我們也可以導入具名導出的內容。 ES6 模塊系統 在 ES6 之前,我們已經知道了 RequireJS,AngularJS 的依賴注入,以及 CommonJS,具體可以看筆者的上一篇文章《JS...
摘要:和必須始終顯示在其各自用法的頂級范圍中。也就是說不可以在條件中放置或它們必須放在所有塊和函數之外。不幸的是,它存在一些缺點,并正式地不鼓勵這樣做。用戶可以另外手動將和列為命名導入,如果他們想要的話。 ES6提供了兩個關鍵字import導入和export導出,語法上有些差別。!important: import和export必須,始終顯示在,其各自用法的,頂級范圍中。也就是說不可以在if...
摘要:模塊可以導入和導出各種類型的變量,如函數,對象,字符串,數字,布爾值,等等。所以這可能會導致一些不符合預期的行為。可變的基本類型值在導入一些基本類型的值如數字,布爾值或字符串時,可能會產生一個有趣的副作用。 前言 ECMAScript 2015(又稱ES6)提供了一個前端JavaScript缺失已久的特性 —— 模塊。ES2015中的模塊參考了CommonJS規范(目前Node.js的...
摘要:盲目使用替換后可能會導致預期意外的結果。在中,許多種方法來處理函數的參數默認值,參數數量,參數命名。此外,處理后的值,無論是解決還是拒絕的結果值,都是不可改變的。 這是一個 ES2015(ES6) 的Cheatsheet,其中包括提示、小技巧、最佳實踐和一些代碼片段,幫助你完成日復一日的開發工作。 Table of Contents var 與 let / const 聲明 代碼執行...
摘要:目前主流的模塊規范模塊通用模塊如果你在文件頭部看到這樣的代碼,那么這個文件使用的就是規范實際上就是全局變量這三種風格的結合這段代碼就是對當前運行環境的判斷,如果是環境就是使用規范,如果不是就判斷是否為環境,最后導出全局變量有了后我們的代碼和 目前主流的模塊規范 UMD CommonJs es6 module umd 模塊(通用模塊) (function (global, facto...
閱讀 1075·2021-09-29 09:35
閱讀 4621·2021-09-22 15:24
閱讀 1449·2021-07-25 21:37
閱讀 2178·2019-08-30 14:17
閱讀 965·2019-08-30 13:56
閱讀 2411·2019-08-29 17:07
閱讀 1250·2019-08-29 12:44
閱讀 2705·2019-08-26 18:26