ES6 экспорт по умолчанию с несколькими функциями, ссылающимися друг на друга
в es6 там вы можете определить модуль таких функций, как этот
export default {
foo() { console.log('foo') },
bar() { console.log('bar') },
baz() { foo(); bar() }
}
выше, как представляется, действительный код, но если я вызываю baz()
, он выдает ошибку:
ReferenceError: foo is not defined
Как вы вызываете foo
из другой функции? в этом случае baz
Edit
Здесь код, который на самом деле не работает. Я упростил код, поэтому он должен только ядро
const tokenManager = {
revokeToken(headers) {
...
},
expireToken(headers) {
...
},
verifyToken(req, res, next) {
jwt.verify(... => {
if (err) {
expireToken(req.headers)
}
})
}
}
export default tokenManager
и ошибка
expireToken(req.headers);
^
ReferenceError: expireToken is not defined
Изменить 2
Я просто попробовал добавить tokenManager
до expireToken
и, наконец, работает
Ответы
Ответ 1
Конструкция export default {...}
- это просто ярлык для чего-то вроде этого:
const funcs = {
foo() { console.log('foo') },
bar() { console.log('bar') },
baz() { foo(); bar() }
}
export default funcs
Теперь становится очевидным, что в области модуля нет функций foo
, bar
или baz
. Но есть объект с именем funcs
(хотя на самом деле он не имеет имени), который содержит эти функции в качестве своих свойств и который станет экспортом по умолчанию модуля.
Итак, чтобы исправить ваш код, перепишите его без использования ярлыка и обратитесь к foo
и bar
в качестве свойств funcs
:
const funcs = {
foo() { console.log('foo') },
bar() { console.log('bar') },
baz() { funcs.foo(); funcs.bar() } // here is the fix
}
export default funcs
Другой вариант - использовать ключевое слово this
для ссылки на объект funcs
, не указывая явно, как указывал @pawel.
Еще один вариант (и тот, который я обычно предпочитаю) заключается в объявлении этих функций в области модуля. Это позволяет напрямую обращаться к ним:
function foo() { console.log('foo') }
function bar() { console.log('bar') }
function baz() { foo(); bar() }
export default {foo, bar, baz}
И если вы хотите удобство экспорта по умолчанию и возможность импорта элементов по отдельности, вы также можете экспортировать все функции по отдельности:
// util.js
export function foo() { console.log('foo') }
export function bar() { console.log('bar') }
export function baz() { foo(); bar() }
export default {foo, bar, baz}
// a.js, using default export
import util from './util'
util.foo()
// b.js, using named exports
import {bar} from './util'
bar()
Или, как предложил @loganfsmyth, вы можете обойтись без экспорта по умолчанию и просто использовать import * as util from './util'
, чтобы получить все именованные экспортные данные в одном объекте.
Ответ 2
Один из вариантов - изменить ваш модуль. Как правило, если вы экспортируете объект с кучей функций на нем, проще экспортировать кучу названных функций, например.
export function foo() { console.log('foo') },
export function bar() { console.log('bar') },
export function baz() { foo(); bar() }
В этом случае вы экспортируете все функции с именами, чтобы вы могли сделать
import * as fns from './foo';
чтобы получить объект со свойствами для каждой функции вместо импорта, который будет использоваться для вашего первого примера:
import fns from './foo';
Ответ 3
tl; dr: baz() { this.foo(); this.bar() }
В ES2015 эта конструкция:
var obj = {
foo() { console.log('foo') }
}
равен этому ES5-коду:
var obj = {
foo : function foo() { console.log('foo') }
}
exports.default = {}
похож на создание объекта, ваш экспорт по умолчанию преобразуется в код ES5 следующим образом:
exports['default'] = {
foo: function foo() {
console.log('foo');
},
bar: function bar() {
console.log('bar');
},
baz: function baz() {
foo();bar();
}
};
теперь это очевидно (я надеюсь), что baz
пытается вызвать foo
и bar
, определенные где-то во внешней области, которые undefined. Но this.foo
и this.bar
будут решаться с помощью ключей, определенных в объекте exports['default']
. Таким образом, экспорт по умолчанию, ссылающийся на свои собственные методы, выглядит следующим образом:
export default {
foo() { console.log('foo') },
bar() { console.log('bar') },
baz() { this.foo(); this.bar() }
}
См. babel repl transpiled code.