0

Все текущие модульные погрузчики, как AMD,CommonJS,SystemJS с использованием определений переменных для загрузки внешних объектов в текущем модуле объемДинамический ES6 модуль прицелы

как:

var something = require('something'); 

или:

define('module',['something'],function(something){}); 

В случае когда вы не знаете, что вам нужно импортировать из внешнего модуля, или просто нужно импортировать все, это становится проблемой, поскольку невозможно определить переменную во время выполнения.

Я предполагаю, что это главная причина, почему ES6 переводчики не используя

import * from 'something'; 

синтаксис и они не включены в это ES6 Spec.

Так, говоря динамический модуль сферы я имею в виду, что переменные модуля могут быть определены/загружены во время выполнения, что позволит расширить синтаксис ES6 к чему-то как:

import * from 'something'; 
import Something.* from 'something'; 
import /regexp/ from 'something'; 

На мой взгляд, это более оптимальный способ определения импорта, а затем перечислить все имена, как:

import { 
    ONE, 
    TWO, 
    ... 
} from 'something'; 

Теперь мой вопрос:

Почему бы не использовать with для этого?

Вот простой пример перевода из ES6 в ES5, которые могут решить проблему:

файл: модули/модуль-1.js

var localVar = 'VALUE'; 
function localFun(a,b){ 
    return a +' and '+ b; 
} 
export { 
    localVar as module1Var 
    localFun as module1Fun 
} 

к:

(function(){ 
    // define module named 'modules/module-1' 
    // and return related scope object 
    // containing 'execute_module' function predefined 
    with (define_module('modules/module-1')) { 
     // will register actual module execution 
     // which will be called after all imports 
     // initialized 
     execute_module(function(){ 
      var localVar = 'VALUE'; 
      function localFun(a,b){ 
       return a +' and '+ b; 
      } 
      // returns value as current module exports 
      return { 
       module1Var : localVar, 
       module1Fun : localFun 
       // ... 
      }; 
     }); 
    } 
})(); 

файл: modules/module-1.js

import * from 'modules/module-1.js'; 

console.info(module1Fun(module1Var)); //prints: VALUE and VALUE 

к:

(function(){ 
    // define module named 'modules/module-2' 
    // after execute is called loader will do 
    // all imports and bind exports from modules 
    // to current module scope and then invoke callback 
    // after which imported variables will appear in with scope 
    // and will be visible in callback scope. 
    with (define_module('modules/module-2',{ 
     'modules/module-1' : '*', 
     // also can filter exports by regexp 
     'modules/other' : /.*/ 
    })) { 
     execute_module(function(){ 
      console.info(module1Fun(module1Var)); //prints: VALUE and VALUE     
     }); 
    } 
})(); 

это действительно необходимо, чтобы избежать with даже в transpilers/погрузчиками?

Я по достоинству оценит ваши мысли об этих парнях, потому что я подумываю написать еще один переводчик ES6to5 и загрузчик модулей. :)

+0

Почему вы хотите написать транспилер, который не соответствует спецификации? Для меня это не имеет смысла. Конечно, вы можете делать все, что хотите, и использовать свой собственный диалект JS. –

ответ

2

Итак, есть несколько причин не делать этого ...

... во-первых, это просто, что в JS плохо использовать практику использования рабочего контекста с глобальными или «глобальными» переменными, не зная, что это за переменные.

Если содержимое этого импорта изменяется, и я использую код with (что действительно не является действительным ES5 ... ... ES5 - это подмножество Strict Mode, with остается включенным, чтобы разрешить запуск кода ES3 в ES5 браузерах без взрыва), то у меня есть гораздо больше беспокоиться о том, чем просто пытается вызвать метод модуля, который изменил ...

// some-module/v1.0/some-module.js 
// ... 
export { doA, doB, a, b } 

// my-app/index.js 
import * with "./some-module/v1.0/some-module"; 

const c = 1; 
let doC = () => doA(a) + doB(b); 

Это выглядит хорошо, конечно. Никакого вреда.

Что делать, если some-module является пакет NPM, и я в Dev-режиме, поэтому я хочу, чтобы постоянно обновлять some-module через функцию-добавляет, потому что я знаю, что некоторые функции сделают мою жизнь легче, когда они приземлятся:

// some-module/v1.5/some-module.js 
export { doA, doB, doC, a, b, c }; 

// my-app/index.js 
import * with "./some-module/v1.5/some-module"; 

const c = 1; 
/* 
    ... 
*/ 
let doC = () => doA(a) + doB(b); 

BOOM!

c is already defined.

Если вы ищете все свои скомпилированные библиотеки/модули/компоненты импорта (предположим, что у вас их 8 в точке входа в приложение) ... ... и вы, наконец, найдете источник, который импортирует c в качестве глобального, и вы обновите все свой код, чтобы заменить имя своего c на что-то еще, а затем заменить все ссылки на него, чтобы они больше не взорвались, что будет дальше?

BOOM! doC is already defined.

Повторите этот процесс и найдите повреждающий файл.

Как мы решаем эти проблемы?
Как правило, это через пространство имен.

У нас уже есть namespace в тех import заявлениях, которые работают в основном - отлично (с дальнейшими предложениями по еще более упрощению в ES7).

import someModule from "./some-module/v1.0/some-module"; 

let doC = () => someModule.doA(someModule.a) + someModule.doB(someModule.b); 

вдруг, становится ясно видеть, что нет не страха столкновения метода/значения, в любом месте вашего приложения, если это не ваша вина.

Кроме того, если вы загружаете всю библиотеку и решите, что вы хотите сэкономить время с помощью ссылки некоторых этих значений/методов напрямую, вы можете выбрать сделать это.

import someModule from "./some-module/v1.5/some-module"; 
const { a, b } = someModule; 
let { doA, doB } = someModule; 

const c = 1; 
let doC = () => doA(a) + doB(b) + someModule.doC(c); 

Там еще 0% двусмысленность, и все же весь код был сохранен как можно, благодаря давая потребителю выбор, как обращаться с импортом.

+0

Извините, не нашел способа прокомментировать ваш ответ, поэтому я ответил как комментарий к вашему ответу :) –

+0

Плюс один для использования слова «slather». –

0

@norguard, хороший улов на "строгого режима" и обновлений модулей, но:

строгий режим все еще могут быть использованы в реальных условиях выполнения обратного вызова

боны! определения области локального выполнения переопределяют (скрывают) определения с областью действия в текущем контексте, поэтому нет проблем с переопределением.

// some-module/v1.5/some-module.js 
export { doA, doB, doC, a, b, c }; 
// my-app/index.js 
import * with "./some-module/v1.5/some-module"; 
const c = 1; 
/* 
    ... 
*/ 
let doC = () => doA(a) + doB(b); 

// translated to: 
(function(){ 
    // with scope contain { doA, doB, doC, a, b, c } 
    with (define_module('my-app/index.js',{ 
     'some-module/v1.5/some-module.js':'*' 
    })) { 
     execute_module(function(){ 
      "use struct" 

      // local var 'c' overrides definition 'c' of 'with scope' 
      // in current function context. 
      var c = 1; 
      // same for 'doC' function 
      var doC = function(){return doA(a) + doB(b)}; 

     }); 
    } 
})(); 

Так что все выше по-прежнему будет работать.

+0

Я действительно не уверен, что вы надеетесь выбраться из этого. Во-первых: спецификация ожидает, что «import myModule из« my-module »;» будет равен «var myModule = require (« my-module »). Default;', как он есть. Эта переменная определена * в корневой области модуля * и *** только *** в корневой области модуля (фактически недействительно использовать операторы 'import' /' export' в любой области, отличной от верхней уровень файла, в котором вы работаете. Кроме того, как я уже упоминал, если у вас было 8 файлов, которые вы «находились в вашем« index.js », каждый из которых имел 5-10 ИТ, был« с », потенциально прохождение через ... – Norguard

+0

... как вы разрешаете это? Является ли теперь частью спецификации JS, что модули, от которых я зависим, теперь зависят от заказа? Если я импортирую «1.js», «2.js» и «3.js», следует ожидать, что мои глобальные переменные будут отличаться от «3.js» «2.js» «1.js»? Последнее - «Временная мертвая зона». Я не могу использовать 'let' или 'const', чтобы определить что-то уже инициализированное в этой текущей области.Кроме того, я не могу ссылаться на значение * выше *, на которое он ссылается, включая теневое. Таким образом, если вы согласитесь со всей спецификацией, это нарушает. хорошо ... ... но это ваша прерогатива ... – Norguard