简体   繁体   中英

How to access exported "nested" functions in Nodejs - TypeError: is not a function

This is a case of exported nested modules:

BaseTutorial.js

// exports module makes the functions public such that they can be accessed in other modules in Node.js.
module.exports.fun_tutorial = function()
{
    console.log("First print from Tutorial.js")                                
}

Extended_NodeTutorial.js

    // `require` is the way to include other modules in

var obj_baseTutorialJS = require('./Base_Tutorial.js');

module.exports.fun_extendedNodeTutorial = function()
{
    console.log("Second print from Extended_NodeTutorial.js")

    this.ss = function fun_nested()         
    {
        console.log("sadasdsa")
        var fun_nested = obj_baseTutorialJS
        fun_nested.fun_tutorial();
    }
}

app.js

var obj_extendedNodeTutorial = require('./Extended_NodeTutorial.js');
console.log(obj_extendedNodeTutorial)

obj_extendedNodeTutorial.fun_extendedNodeTutorial();
obj_extendedNodeTutorial.fun_extendedNodeTutorial.fun_nested();

Error after executing node app.js :

{ fun_extendedNodeTutorial: [Function] }
Second print from Extended_NodeTutorial.js
/home/***/Documents/home_notes/MEAN/app.js:7
obj_extendedNodeTutorial.fun_extendedNodeTutorial.fun_nested();
                                                  ^

TypeError: obj_extendedNodeTutorial.fun_extendedNodeTutorial.fun_nested is not a function
    at Object.<anonymous> (/home/***/Documents/home_notes/MEAN/app.js:7:51)
    at Module._compile (module.js:569:30)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:503:32)
    at tryModuleLoad (module.js:466:12)
    at Function.Module._load (module.js:458:3)
    at Function.Module.runMain (module.js:605:10)
    at startup (bootstrap_node.js:158:16)
    at bootstrap_node.js:575:3

I don't know what you're trying to achieve but there are multiple ways you can solve this problem.

1) You can return your nested function.

BaseTutorial.js

module.exports.fun_tutorial = function()
{
    console.log("First print from Tutorial.js")                                
}

Extended_NodeTutorial.js

var obj_baseTutorialJS = require('./Base_Tutorial.js');

module.exports.fun_extendedNodeTutorial = function()
{
    console.log("Second print from Extended_NodeTutorial.js");

    return fun_nested()
    {
        console.log("sadasdsa");
        const fun_tutorial = obj_baseTutorialJS.fun_tutorial;
        fun_tutorial();
    }
}

app.js

var obj_extendedNodeTutorial = require('./Extended_NodeTutorial.js');
console.log(obj_extendedNodeTutorial)

const fun_nested = obj_extendedNodeTutorial.fun_extendedNodeTutorial();
fun_nested(); // adasdsa

2) You can create an instance of the function exported from Extended_NodeTutorial.js . I see you're trying to use this.ss . To achive something similar to that you'll have to make use of new keyword.

BaseTutorial.js

module.exports.fun_tutorial = function()
{
    console.log("First print from Tutorial.js")                                
}

Extended_NodeTutorial.js

var obj_baseTutorialJS = require('./Base_Tutorial.js');

module.exports.fun_extendedNodeTutorial = function()
{
    console.log("Second print from Extended_NodeTutorial.js")

    this.fun_nested = function()
    {
        console.log("sadasdsa");
        const fun_nested = obj_baseTutorialJS.fun_tutorial;
        fun_tutorial();
    }
}

app.js

var obj_extendedNodeTutorial = require('./Extended_NodeTutorial.js');
console.log(obj_extendedNodeTutorial)

const fun_extendedNodeTutorial = new obj_extendedNodeTutorial.fun_extendedNodeTutorial(); // Second print from Extended_NodeTutorial.js
fun_extendedNodeTutorial.fun_nested(); // sadasdsa

This a prototype inheritance issue. You should either use constructor.prototype to define your fun_nested function and use it whenever you want:

var obj_baseTutorialJS = require('./Base_Tutorial.js');

module.exports.fun_extendedNodeTutorial = function()
{
    console.log("Second print from Extended_NodeTutorial.js")
}

module.exports.fun_extendedNodeTutorial.constructor.prototype.fun_nested = function() {
    console.log("sadasdsa")
    var fun_nested = obj_baseTutorialJS
    fun_nested.fun_tutorial();
}

and use it like this:

obj_extendedNodeTutorial.fun_extendedNodeTutorial();
obj_extendedNodeTutorial.fun_extendedNodeTutorial.fun_nested();

or if you define fun_nested inside fun_extendedNodeTutorial using this.ss :

module.exports.fun_extendedNodeTutorial = function()
{
    console.log("Second print from Extended_NodeTutorial.js")

    this.ss = function fun_nested()         
    {
        console.log("sadasdsa")
        var fun_nested = obj_baseTutorialJS
        fun_nested.fun_tutorial();
    }
}

then create an instance of fun_extendedNodeTutorial function and use ss to call fun_nested function:

var extendedNodeTutorial = new obj_extendedNodeTutorial.fun_extendedNodeTutorial();
extendedNodeTutorial.ss();

Both ways will output everything in order:

$ node .\app.js
{ fun_extendedNodeTutorial: [Function] }
Second print from Extended_NodeTutorial.js
sadasdsa
First print from Tutorial.js

It's difficult to advise you since there are many different implementations of nested functions/imports, and the appropriate one largely depends on your use case. I took a guess that you would like to allow access to an imported module from another imported module, and that you'd like to use app.js as written.

You can expose certain variables or modules by setting a property to the exported variable (or in this case, a function). For this example, it would be something like fun_extendedNodeTutorial.fun_nested = obj_baseTutorialJS.fun_tutorial;

BaseTutorial.js

// As previously written
module.exports.fun_tutorial = function()
{
    console.log("First print from Tutorial.js")                                
}

Extended_NodeTutorial.js

var obj_baseTutorialJS = require('./Base_Tutorial.js');

// we'll store fun_extendedNodeTutorial to a variable to later
// assign a property to it
var fun_extendedNodeTutorial = function()
{
    console.log("Second print from Extended_NodeTutorial.js")
}

// this allows outside files to access fun_tutorial via
// fun_extendedNodeTutorial.fun_nested
fun_extendedNodeTutorial.fun_nested = obj_baseTutorialJS.fun_tutorial;

// finally export the function and its nested property
module.exports.fun_extendedNodeTutorial = fun_extendedNodeTutorial;

app.js

// As previously written
var obj_extendedNodeTutorial = require('./Extended_NodeTutorial.js');
console.log(obj_extendedNodeTutorial)

obj_extendedNodeTutorial.fun_extendedNodeTutorial();
obj_extendedNodeTutorial.fun_extendedNodeTutorial.fun_nested();

Here is a slight modification that will not cause the error: abc.js

module.exports.test = () => {
  this.ss = function () {
    return 'From ss'
  }
}

app.js

const abc = require('./abc')
abc.test()
abc.ss()

Basically, when we replace the function keyword with a fat arrow in the abc.js file, the this keyword is bound lexically, which means it is bound to the module.exports object of abc.js . From app.js , we first require abc.js and then run the test method. This will populate the exported object abc with the function ss and you can now access it via the abc object.

When we run it with the following command,

node app.js

We get the string From ss

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM