1

Javascript でオブジェクト コンストラクターを作成するのに問題があります。インスタンス化されたオブジェクトの 1 つで関数を呼び出すと、インスタンス化されたオブジェクトの値が常に返されます。流れは次のようになります。

blue = tool('blue');
blue.jDom();     // returns '[<div id="blue" class="tool">...</div>]'
red = tool('red');
red.jDom();     // returns '[<div id="red" class="tool">...</div>]'
blue.jDom();     // returns '[<div id="red" class="tool">...</div>]'

これは、プロトタイプ宣言に含めたプライベート変数によるものだと思います。プロトタイプ宣言をコンストラクターに移動すると、すべて正常に動作しますが、これは、オブジェクトごとに新しいプロトタイプを作成することによって、オブジェクトがそれ自体ではなく、プロトタイプのプロパティに影響を与えているように見えるという事実を隠しているだけです。ここに私の関連コードがあります:

function beget(oPrototype) {
    function oFunc() {};
    oFunc.prototype = oPrototype;
    return new oFunc()
};    

var tool = (function (){
        var protoTool = function(){

            var oTool = {},
                that = this,
                _bVisible = true,
                _oParentPane = 'body',
                _aoComponents,
                _sName = 'tool',
                _sSelector = '#' + _sName,
                _jDomElement;



            // this is the private tab object, needs to be refactored
                            // descend from a single prototype  
            function _tab() {

                var oTab = {},
                    _sHtml = '<li><a href="' + _sSelector + '">' + _sName + '</a></li>',
                    _jDomElement = $(_sHtml);

                function jDom() {
                    return _jDomElement;
                }

                oTab.jDom = jDom;

                return beget(oTab);
            };

            // this builds the jDom element 
            function _jBuild() {
                var sHtml = '<div id="' + _sName + '" class="tool"></div>';
                _jDomElement = $(sHtml)
                return _jDomElement;
            };

            // this returns the jQuery dom object
            function jDom() {
                if (typeof _jDomElement === 'undefined') {
                    _jBuild();
                }
                return _jDomElement;
            };

            function configure (oO){
                if (typeof oO !== 'undefined') {
                    if (typeof oO === 'string') {
                        var name = oO;
                        oO = Object();
                        oO.sName = name;
                    } 


                    _bVisible = oO.bVisible || _bVisible,
                    _oParentPane = oO.oParentPane || _oParentPane,
                    _aoComponents = oO.aoComponents || _aoComponents,
                    _sName = oO.sName || _sName,
                    _sSelector = '#' + _sName,
                    _jDomElement = undefined;
                    _oTab = _tab();

                    _oTab.jDom()
                        .appendTo(jDom())
                        .draggable({
                        revert: 'invalid',
                        containment: '#main',
                        distance: 10,
                    });
                } 

            };

            oTool.tMove = tMove;
            oTool.bVisible = bVisible;
            oTool.uOption = uOption;
            oTool.jDom = jDom;
            oTool.configure = configure;    

            return oTool;   
        }();

        var tool = function (oO) {
            that = beget(protoTool);
            that.configure(oO);
            that.configure = undefined;
            return that;
        };

        return tool;
    })();
4

1 に答える 1

0

最初 : 'that = beget(protoTool);' による内部ツール var 定義内 「var that = beget(protoTool);」という意味である必要があります。

あなたのコードで何が起こっていますか? :
ツールに値を与えるために、ツール定義が評価されます。この評価中に、protool の周りにクロージャが作成されます。
しかし、このクロージャーは、この評価中に一度だけ行われます。その後のすべての protool への呼び出し (protools をプロトタイプとして持つ「that」への呼び出しによって行われる) は、この最初で唯一のクロージャーの値を変更します。
そのため、この動作が表示されます。クロージャの値が更新されたため、最後に表示されたオブジェクトがすべての注目を集めます。
解決策は、'tool' の内部 var 関数定義内に適切なクロージャを作成することです。

しかし、可能であれば、後で new 演算子を使用して、古典的な JavaScript クラス定義に完全に移行することをお勧めします。これは、コーディング/理解/デバッグがはるかに簡単だと思います。

別の rq : 最新の JavaScript 仕様 (1.8.6) で beget === Object.create

于 2013-07-04T16:37:16.740 に答える