質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

2222閲覧

別のファイルに記述したclass/methodを双方がお互いを参照しようとすると、undefinedエラーとなる

eternalbeginne

総合スコア58

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/10/21 17:43

双方を参照するような構造をしようとすると、xxxx is not a function というエラーが出ます。

子要素を生成することができる親要素を用意したいと思っています。
ここでいう要素とは、たとえばclass Person{}としています。
で、new Person()生成する関数factory()を用意しています。
Personにはchild()関数を用意しており、
factory()を実行して、子要素を作っています。

この仕組みを1ファイルで記述すると成功するのですが、
ファイルを分割して、双方の関数をrequireして使うようにしていると、
次のようなエラーが出てしまいます。

TypeError: factory is not a function

どのように解決すればよいでしょうか??

コード例です。

factory.js

javascript

1const {Person} = require("./Person"); 2 3function factory(){ 4 return new Person() 5} 6module.exports = { 7 factory 8}; 9

Person.js

javascript

1const {factory} = require("./factory"); 2 3class Person{ 4 constructor() {} 5 say(){ 6 return "hello"; 7 } 8 child(){ 9 return factory() // ←このfactory()がundefinedだと怒られます。 10 } 11} 12module.exports = { 13 Person 14};

メイン処理
main.js

const {factory} = require("./factory"); const parent = factory() parent.say() // "hello" parent.child().say() // "helloとでてほしい" parent.child().child().say() // "helloとでてほしい"

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

循環参照と呼ばれるダメなパターンですね。
相互のrequireを行うと、空のオブジェクトになるようです。
参考記事: node.jsにおける循環参照に対処するための3つの方法 - Qiita

クラスは起点となる事が多いので、
何かに依存させるとすぐ循環参照になって不便です。

メソッド内で実行した時に初めてrequireする手法とかありますが、
ESModulesやWebpackで動いたり動かなかったりであまりオススメじゃないですね。

ここはDIを前提とした設計にすると良いですよ。
例えばchildrenを作るfactory関数を外部から注入する感じですかね。
依存のフローが確実に上から下になるので循環参照を解消できます。

class Person{ constructor(factory) { this.factory = factory } say(){ return "hello" } child(){ return this.factory() } } function factory () { return new Person(factory) } factory().child().child().say() // "hello"

投稿2020/10/22 08:27

miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

eternalbeginne

2020/11/03 16:41

この発想を持っていませんでした。ありがとうございます! function factory () { return new Person(factory) }
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問