JavaScript実装extend

3771 ワード

最近、モバイル側のプロジェクトを書いていますが、まだライブラリを参照していないので、自分で書く方法がたくさんあります.
jQueryは使い慣れており、関数パラメータがオブジェクトの場合、デフォルトパラメータを定義するときにdefaultOptionsオブジェクトが書き込まれ、jQuery.extendを介してdefaultOptionsオブジェクトに実パラメータが拡張されます.JavaScriptにはextendというオリジナルの方法はありませんが、今日は暇なので、自分で一つ実現しましょう.
まずこの関数に何をする必要があるか考えてみましょう.jQuery extendドキュメントに記述するjQuery.extendのプロトタイプはjQueryである.extend( target [, object1 ] [, objectN ] )
object 1、object 2を...targetにマージし、マージしたtargetを返します.この中には2つの点に注意しなければならない.
  • 合併は後から前へである.
  • targetの値は修正されました.
  • は深くコピーされています(パラメータオブジェクトに属性がオブジェクトであれば、再帰的にマージされます).

  • 元のデータを変更したくないのも簡単ですが、最初のパラメータでオブジェクトを空にすればいいのです.
    じゃあ、直接先代にしましょうか.
    void function(global){
        var extend,
            _extend,
            _isObject;
    
        _isObject = function(o){
            return Object.prototype.toString.call(o) === '[object Object]';
        }
    
        _extend = function self(destination, source){
            for (var property in source) {
                if (source.hasOwnProperty(property)) {
    
                    //  sourc[property]   ,   
                    if (_isObject(source[property])) {
    
                        //  destination  property,     
                        if (!destination.hasOwnProperty(property)) {
                            destination[property] = {};
                        };
    
                        //  destination[property]    ,     
                        if (!_isObject(destination[property])) {
                            destination[property] = {};
                        };
    
                        //   
                        self(destination[property], source[property]);
                    } else {
                        destination[property] = source[property];
                    };
                }
            }
        }
    
        extend = function(){
            var arr = arguments,
                result = {},
                i;
    
            if (!arr.length) return {};
    
            for (i = 0; i < arr.length; i++) {
                if (_isObject(arr[i])) {
                    _extend(result, arr[i])
                };
            }
    
            arr[0] = result;
            return result;
        }
    
        global.extend = extend;
    }(window)
    

    これでいいようです.しかし、小さな問題があるようです.ここではパラメータ順に左から右に順に実行しますが、実際には最後のパラメータにある属性であれば、前のパラメータのこの属性はこれ以上拡張する必要はありません.実は前のすべてのパラメータは自分の持っている属性で、最後のパラメータが持っていない属性を最後のパラメータに補完します.それでも、パラメータリストの右側から拡張したほうがいいのではないでしょうか.
    以降のコードの変更:
    void function(global){
        var extend,
            _extend,
            _isObject;
    
        _isObject = function(o){
            return Object.prototype.toString.call(o) === '[object Object]';
        }
    
        _extend = function self(destination, source) {
            var property;
            for (property in destination) {
                if (destination.hasOwnProperty(property)) {
    
                    //  destination[property] sourc[property]    ,   
                    if (_isObject(destination[property]) && _isObject(source[property])) {
                        self(destination[property], source[property]);
                    };
    
                    //  sourc[property]   ,   
                    if (source.hasOwnProperty(property)) {
                        continue;
                    } else {
                        source[property] = destination[property];
                    }
                }
            }
        }
    
        extend = function(){
            var arr = arguments,
                result = {},
                i;
    
            if (!arr.length) return {};
    
            for (i = arr.length - 1; i >= 0; i--) {
                if (_isObject(arr[i])) {
                    _extend(arr[i], result);
                };
            }
    
            arr[0] = result;
            return result;
        }
    
        global.extend = extend;
    }(window)
    

    コードを書くのはいつもおもしろい!この中にはresultにある属性さえあれば、これ以上値をつける必要はありません.へへ.
    もちろん、現在のレベルは限られています.このコードには最適化の余地があるに違いありません.もし役人が何かアドバイスがあれば、教えてください.