动手DIY一个underscorejs库及underscorejs源码分析2

21 篇文章 0 订阅
12 篇文章 1 订阅

接着第一篇《动手DIY一个underscorejs库及underscorejs源码分析1》

所有代码挂在我的github上。

1.兼容requirejs和seajs模块化

  • requirejs
    在代码的尾部加上
    if (typeof define == 'function' && define.amd) {
        //定义一个模块并且起个名字
        define('_underscore', [], function() {
            return _;
        });
    }

使用测试:代码请点我
demo3.html

<body>
    <script data-main="demo3" src="lib/require.js"></script>
</body>

demo3.js

define(function(require) {
    require(['../DIY/2/_underscore'], function() {
        console.log(_);
    });
});
  • 加上支持seajs的代码
    if (typeof define == 'function' && define.amd) {
        define('_underscore', [], function() {
            return _;
        });
    } else if (typeof define == 'function' && define.cmd) { //seajs
        define(function(require, exports, module) {
            module.exports = _;
        });
    }

使用:
demo2.html

    <script src="lib/sea-debug.js"></script>
    <script>
        seajs.use('./demo2');
    </script>

demo2.js

define(function(require, exports, module) {
    var _ = require('../DIY/2/_underscore');
    console.info(_);
});

2.支持nodejs

root._ = _;

修改为:

  if (typeof exports != 'undefined' && !exports.nodeType) {
    if (typeof module != 'undefined' && !module.nodeType && module.exports) {
      exports = module.exports = _;
    }
    exports._ = _;
  } else {
    root._ = _;
  }

3._.extend

使用:

    console.log(_.extend({name: 'moe'}, {age: 50}));
    //结果Object {name: "moe", age: 50}
    //类似与_.keys
    _.allKeys = function(obj) {
        if (!_.isObject(obj)) return [];
        var keys = [];
        for (var key in obj) keys.push(key);
        // Ahem, IE < 9.
        // if (hasEnumBug) collectNonEnumProps(obj, keys);
        return keys;
    };

主函数:

    var createAssigner = function(keysFunc, defaults) {
        return function(obj) {
            var length = arguments.length;
            if (defaults) obj = Object(obj);
            if (length < 2 || obj == null) return obj;
            for (var index = 1; index < length; index++) {
                var source = arguments[index],
                    keys = keysFunc(source),
                    l = keys.length;
                for (var i = 0; i < l; i++) {
                    var key = keys[i];
                    if (!defaults || obj[key] === void 0) obj[key] = source[key];
            //将参数(对象)放入到obj组合到一起
                }
            }
            return obj;
        };
    };
    _.extend = createAssigner(_.allKeys);
    _.extendOwn = _.assign = createAssigner(_.keys);

4.重要内部函数cb

    var builtinIteratee;
    //如果是函数则返回上面说到的回调函数;
    //如果是对象则返回一个能判断对象是否相等的函数;
    //默认返回一个获取对象属性的函数
    var cb = function(value, context, argCount) {
        if (_.iteratee !== builtinIteratee) return _.iteratee(value, context);
        if (value == null) return _.identity; //默认的迭代器
        if (_.isFunction(value)) return optimizeCb(value, context, argCount);
        if (_.isObject(value)) return _.matcher(value);
        return _.property(value);
    };
    _.iteratee = builtinIteratee = function(value, context) {
        return cb(value, context, Infinity);
    };

4.1 _.identity

很简单但是是默认的迭代器

    _.identity = function(value) {
        return value;
    };

测试很简单

    var obj1 = {name:'zry'};
    console.log(obj1 === _.identity(obj1));//true

4.2 _.matcher

    _.matcher = _.matches = function(attrs) {
        attrs = _.extendOwn({}, attrs);
        return function(obj) {
            return _.isMatch(obj, attrs);
        };
    };
    //两个对象是不是全等于。给定的对象是否匹配attrs指定键/值属性
    _.isMatch = function(object, attrs) {
        var keys = _.keys(attrs),
            length = keys.length;
        if (object == null) return !length;
        var obj = Object(object);
        for (var i = 0; i < length; i++) {
            var key = keys[i];
            if (attrs[key] !== obj[key] || !(key in obj)) return false;
        }
        return true;

    };

测试:

    var obj2 = {selected: true, visible: true};
    var ready = _.isMatch(obj2,{selected: true, visible: true});
    //返回一个断言函数,这个函数会给你一个断言 可以用来辨别 
    //给定的对象是否匹配attrs指定键/值属性
    console.log(ready);//true

4.3 _.property

property函数在第一篇博客中已经实现

    _.property = property;

5._.map

    _.map = _.collect = function(obj, iteratee, context) {
        iteratee = cb(iteratee, context);
        var keys = !isArrayLike(obj) && _.keys(obj),
            length = (keys || obj).length,
            results = Array(length);
        for (var index = 0; index < length; index++) {
            var currentKey = keys ? keys[index] : index;
            results[index] = iteratee(obj[currentKey], currentKey, obj);
            //返回的是(value,key,obj)
        }
        return results;
    };

6._.filter

    _.filter = _.select = function(obj, predicate, context) {
         var results = [];
        predicate = cb(predicate, context);
        _.each(obj, function(value, index, list) {
            if (predicate(value, index, list)) results.push(value);
        });
        return results;
    };

测试:

var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });//[2,4,6]

7.两个常用的工具函数_.escape,_.unescape`

7.1 _.escape

要过滤的字符串

    var escapeMap = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#x27;',
        '`': '&#x60;'
    };

主函数

    var createEscaper = function(map) {
        var escaper = function(match) {//match 匹配的子串
            return map[match];
        };
        var source = '(?:' + _.keys(map).join('|') + ')';
        var testRegexp = RegExp(source);
        var replaceRegexp = RegExp(source, 'g');
        return function(string) {
            string = string == null ? '' : '' + string;
            return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
        };
    };

注意值了的string.replace函数第二个参数是个函数,那么返回的数据第一个是match(匹配的子串)

变量名代表的值
match匹配的子串。(对应于上述的$&。)
p1,p2, …假如replace()方法的第一个参数是一个RegExp对象,则代表第n个括号匹配的字符串。(对应于上述的 1 2等。)
offset匹配到的子字符串在原字符串中的偏移量。(比如,如果原字符串是“abcd”,匹配到的子字符串时“bc”,那么这个参数将是1)
string被匹配的原字符串。
_.escape = createEscaper(escapeMap);

测试:

console.log(_.escape('Curly, Larry & Moe')//Curly, Larry &amp; Moe

7.2 _.unescape

反转要过滤的字符串

    _.invert = function(obj) {
        var result = {};
        var keys = _.keys(obj);
        for (var i = 0, length = keys.length; i < length; i++) {
            result[obj[keys[i]]] = keys[i];
        }
        return result;
    };
    var unescapeMap = _.invert(escapeMap);
    _.unescape = createEscaper(unescapeMap);

测试:

console.log(_.unescape('Curly, Larry &amp; Moe'));//Curly, Larry & Moe

参考阅读:
- http://underscorejs.org/
- underscorejs中文:http://www.bootcss.com/p/underscore/
- UnderscoreJS精巧而强大工具包
- JS高手进阶之路:underscore源码经典

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值