获取JSDoc以正确记录嵌套闭包

Sea*_*ema 5 javascript jsdoc jsdoc3

我有一个结构良好的大型JavaScript对象,它是这样的:

/**
 * My 'class' begins here.  JSDoc barfs on this.
 */
var MyClass = (function(window, document, $) {

    return function(options) {

        "use strict";

        var
            x = 123,

            /**
             * This is a "public" function.
             */
            myFunc = function() { /*...*/ },

            /**
             * This is some other "private" function.
             */
            otherFunc = function() { /*...*/ };

        return {
            myFunc: myFunc
        };
    };

})(window, document, window.jQuery);
Run Code Online (Sandbox Code Playgroud)

实际上,最外层的闭包用于控制实现模块模式形式的内部闭包所看到的全局范围:内部函数实际上是一个构造函数,它的嵌套函数是有效的方法,返回的对象实际上是一个它的哪些部分是"公共"的列表.

JSDoc讨厌这个.

(为了记录,我正在使用JSDoc 3.4.)

我试过几个变种@lend,并@export@namespace@memberof在大量的在这个代码的地方,但无论我做什么,JSDoc拒绝注意到任何的内部功能在所有-它不只是"没有他们正确的事情联系起来;" 它根本不包含在任何输出文件中.

这是一个很好的模式,用于紧密封装经典JavaScript,不仅封装其内部结构,还包括其依赖性,而我们的实际应用程序在数千行代码中使用此模式.所以我们的JavaScript本身不会很快改变结构:只有评论可以合理地改变.

我希望能够使用JSDoc来记录这个应用程序,但无论我给它什么,JSDoc都会在这方面失败.在StackOverflow上讨论已经确定了处理各种众所周知的模块系统的方法,但是我还没有找到使用多重嵌套闭包的普通JavaScript的可靠答案.

那么有没有人有办法让JSDoc正确地生MyClass成为"类似"的构造,其中的函数深深地嵌套在其中作为"类"的"方法"?我可以将标记otherFunc@private标记为隐藏,或者必须标记myFunc@public或标记为可见,但无论我尝试什么,JSDoc似乎都不想记录任何嵌套功能完全.

Chr*_*ton 2

我知道这是一个死灵,但确实没有任何关于此的好的文档,所以就这样吧。我花了整整两天的时间阅读其他人的代码并尝试解决这个问题。这是使用3.6.7

基本上:

  1. 您必须使用命名空间,但 JSDoc 不喜欢命名空间与函数同名,因此您必须通过在所有函数命名空间前面加上波形符来隐藏命名空间相同的事实。~ 波浪号本身不会出现在文档中,但如果没有它们,JSDoc 会感到困惑。这在我能找到的任何地方都没有真正记录下来,我是从 JSDoc 处理返回值的方式推断出来的。

  2. 您需要有一个基于实际属性的“根”命名空间。const ClosureDoc = {version: "1.0.0"};在下面的代码中,在/** @namespace */标注下方。尝试放下实际的物体并仅仅拥有/** @namespace ClosureDoc */是行不通的。不知道为什么,而且这在任何地方都没有记录。

  3. 您需要手动显式命名所有内部函数。所有作为函数的返回值也必须手动显式定义,但如果使用的话,实际上不需要@typedef * @returns {outerScope~innerScope}(注意波浪号)

总而言之,为了获得非常合理的代码的非常简单的结果,这似乎需要大量的手工操作,但这是可以做到的。

`

'use strict';
/** @namespace */
const ClosureDoc = {version: "1.0.0"};

/**
 * Outer scope is used to enclose the inner scope
 * @function outerScope
 * @returns {outerScope~innerScope}
 * @returns {outerScope~logInnerMap}
 * @memberof ClosureDoc
 */
function outerScope () {
    /**@namespace ClosureDoc.~outerScope */
    const outerState = {
        innerMap: {}
    }

    const newInnerScope = (name) => (outerState.innerMap[name] = innerScope(name));
    const namedInnerScope = (name) => !(name in outerState.innerMap) ? newInnerScope(name) : outerState.innerMap[name];

    /**
     * Inner Scope is used inside the outer scope
     * @function innerScope
     * @param {string} name
     * @returns {innerScope~logScopeName}
     * @memberof ClosureDoc.~outerScope
     */
    function innerScope(name) {
        /**@namespace ClosureDoc.~outerScope.~innerScope */
        /**
         * Logs the name passed to the inner scope
         * @function logScopeName
         * @memberof ClosureDoc.~outerScope.~innerScope
         */
        function logScopeName() {
            console.log(name);
        }
        return {
            logScopeName
        }
    } 
    /**
     * Logs the map of all scope names
     * @function logInnerMap
     * @memberof ClosureDoc.~outerScope
     */
    function logInnerMap() {
        console.log(outerState.innerMap);
    }
   return {
       namedInnerScope,
       logInnerMap
    }
}

const outer = outerScope();
const inner_1 = outer.namedInnerScope("Bob");
const inner_2 = outer.namedInnerScope("Dole");
inner_1.logScopeName();
inner_2.logScopeName();
outer.logInnerMap();
Run Code Online (Sandbox Code Playgroud)

`