1. ホーム
  2. javascript

[解決済み] ES6 export defaultで複数の関数が互いに参照し合う場合

2022-11-02 03:45:33

質問

es6では、以下のような関数のモジュールを定義することができます。

export default {
    foo() { console.log('foo') }, 
    bar() { console.log('bar') },
    baz() { foo(); bar() }
}

は有効なコードのように見えますが、もし私が baz() を呼び出すと、エラーを投げます。

ReferenceError: foo is not defined

どのように foo を別の関数から呼び出すにはどうしたらよいでしょうか? この場合 baz

編集

実際に動作しないコードはこちらです。私はコードを簡略化したので、必要なのはコア部分だけです。

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 で、ようやく動くようになりました。

どのように解決するのですか?

この export default {...} の構造は、このようなもののためのショートカットに過ぎません。

const funcs = {
    foo() { console.log('foo') }, 
    bar() { console.log('bar') },
    baz() { foo(); bar() }
}

export default funcs

がないことはもう明らかでしょう。 foo , bar または baz という関数がモジュールのスコープにあります。しかし funcs (という名前のオブジェクトがあり(実際には名前はありませんが)、そのプロパティとしてこれらの関数を含んでいて、それがモジュールのデフォルトのエクスポートになります。

ですから、あなたのコードを修正するには、ショートカットを使わずに書き直し、そのコードを参照するために foobar のプロパティとして 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' を使って、1つのオブジェクトですべての名前付きエクスポートを取得することもできます。