0

クローン関数をjavascriptで書いています。

その関数はオブジェクトを再帰的に複製し(循環参照を回避)、うまく機能しているように見えますが、オブジェクト(あるレベルで)にオブジェクト参照が組み込まれている場合、複製されたオブジェクトのプロパティ(正しいように見えます)にアクセスしようとすると、タイプエラー。

これは、datetime を使用した私の簡単な例です (datetime オブジェクトをクローンするためのより効率的な方法があることは知っていますが、それは私の関心事ではありません。私がする必要があるのは、一般的なビルド オブジェクトを複製することです。datetimes は単なる例です)。関数と配列のみをシャローコピーし、オブジェクト(内部配列と関数を除く)をディープコピーし、循環参照を回避しないメソッドへのメソッド。これはエラーの説明にすぎません (完全なクローン機能で得られるのと同じエラーです)。

コード :


        var date = new Date () ;
        var dateProto = date.__proto__ ;

        var cloned = {} ;
        var clonedProto = {} ;

        function clone ( obj )
        {
            if ( obj instanceof Array )
                return [] ;

            if ( obj instanceof Function )
                return obj ;

            if ( obj instanceof Object )
            {
                var result = {} ;
                var elems = Object.getOwnPropertyNames(obj) ;
                var len = elems.length ;
                for ( var i = 0 ; i < len ; i++  )
                {
                    var prop = elems[i] ;
                    var elem = obj[prop] ;

                    result [ prop ] = clone ( elem ) ;
                }

                return result ;
            }

            return obj ;
        }

        cloned = clone ( date ) ;
        clonedProto = clone ( dateProto ) ;

        cloned.__proto__ = clonedProto ;

        alert ( cloned.getDay() );

しかし、これにより getDay メソッドにアクセスしようとすると、この型エラーが発生します: Uncaught TypeError: this is not a Date object.

しかし、私はまだ理由を理解していません.クローンが日付オブジェクトのように見える. "クローン") ですが、エラーではありません。

では、なぜこのエラーが発生するのでしょうか?

助けてくれてありがとう、私の悪い英語でごめんなさい。


編集済み

提案された新しいアイデア (コメントで jfriend00 によって投稿されたフォーム RobG とフォーム記事の両方) に従って、クローン関数 i をそのように書き直しました。

                    function clone ( obj )
        {
            if ( obj instanceof Array )
                return [] ;

            if ( obj instanceof Function )
                return obj ;

            if ( obj instanceof Object )
            {
                var result = new obj.constructor() ;

                result.__proto__ = clone ( obj.__proto__ ) ;

                var elems = Object.getOwnPropertyNames(obj) ;
                var len = elems.length ;
                for ( var i = 0 ; i < len ; i++  )
                {
                    var prop = elems[i] ;
                    var elem = obj[prop] ;

                    result [ prop ] = clone ( elem ) ;
                }

                return result ;
            }

            return obj ;
        }

期待どおりに動作するようになりましたが、このコードの理由がわかりません: var result = new obj.constructor() ; 差をつける。

助けてくれてありがとう。

4

1 に答える 1

1

オブジェクトがプレーン オブジェクト以外の他のタイプのオブジェクト (Date オブジェクトなど) である場合、複製された Date オブジェクトを作成するのではなく、プレーン オブジェクトを作成します。

さらに、複製されたオブジェクトにプロパティをコピーする場合、オブジェクトにプロパティを直接コピーするだけであり、Object.getOwnpPropertyNames()返されるプロトタイプ チェーン内のプロパティはコピーしません。したがって、複製された Date オブジェクトには Date メソッドがありません。

RobG の提案に従って、リターンの直前に次の最初の行を追加します。

result.__proto__ = obj.__proto__;
return result ;
于 2013-06-03T23:59:07.313 に答える