Подтвердить что ты не робот

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 и, наконец, работает

4b9b3361

Ответ 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.