文章出處

// 1. 不污染全局環境
(function() {

    // 2. 保留之前同名變量
    var previousUnderscore = window._;


    var _ = function(obj) {
        return new wrapper(obj);
    };

    // 模塊化
    if (typeof define === 'function' && define.amd) {
        define('underscore', [], function() {
            return _;
        });
    } else if (typeof exports !== 'undefined') {
        if (typeof module !== 'undefined' && module.exports) {
            exports = module.exports = _;
        }
        exports._ = _;
    } else {
        window['_'] = _;
    }


    // 3. undersocre鏈式方案
    var wrapper = function(obj) {
        this._wrapped = obj;
    };

    // 鏈式包裝函數
    var result = function(obj, chain) {
        return chain ? _(obj).chain() : obj;
    };

    // 觸發可鏈式函數
    wrapper.prototype.chain = function() {
        // this._chain用來標示當前對象是否使用鏈式操作
        this._chain = true;
        return this;
    };

    // 當觸發可鏈式后,用這個來取結果值
    wrapper.prototype.value = function() {
        return this._wrapped;
    };

    // 4.將_的靜態方法,賦值給_對象
    var ArrayProto = Array.prototype,
        forEach = ArrayProto.forEach,
        push = ArrayProto.push;
    _.each = forEach;

    _.type = function(obj){
        return Object.prototype.toString.call(obj).slice(8,-1).toLowerCase();
    }

    _.isFunction = function(fn){
        return (_.type(fn) == "function");
    }

    _.functions = function(obj) {
        var names = [];
        for (var key in obj) {
            if (_.isFunction(obj[key])) names.push(key);
        }
        return names.sort();
    }

    _.mixin = function(obj) {
        forEach.call(_.functions(obj), function(name) {
            var func = _[name] = obj[name];
            _.prototype[name] = function() {
                var args = [this._wrapped];
                push.apply(args, arguments);
                return result( func.apply(_, args),this._chain);
            };
        });
    };

    // _是返回wrapper的實例,該實例沒有_.protoype的方法
    // 所以把 _.prototype 指向了  wrapper.prototype,
    // 之后往_.prototype添函數,也就是向wrapper.prototype添函數
    _.prototype = wrapper.prototype;
    _.prototype.constructor = _;
    _.mixin(_);

    // 5.擴展_對象的方法
    // 這些數組方法本身不可鏈式
    forEach.call(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {

        var method = ArrayProto[name];
        wrapper.prototype[name] = function() {
            var wrapped = this._wrapped;
            // 調用Array對應的方法并返回結果
            method.apply(wrapped, arguments);
            var length = wrapped.length;
            if ((name == 'shift' || name == 'splice') && length === 0) {
                delete wrapped[0];
            }
            return result(wrapped, this._chain);
        };
    });


    // 這些數組方法本身可鏈式
    forEach.call(['concat', 'join', 'slice'], function(name) {
        var method = ArrayProto[name];
        wrapper.prototype[name] = function() {
            return result(method.apply(this._wrapped, arguments), this._chain);
        };
    });



})();


// 使用實例

// 不可鏈式方法,使其可鏈式
// var errorTest = [1,2].push(3).push(4); // push這個函數返回的是函數長度,所以這里會報錯
var underscore_obj = _([1, 2]).chain().push(3).push(4);
var result_arr = underscore_obj.value();
console.log(result_arr);

 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()