Underscore骨骼

转一篇underscore的文章给大家

underscore函数大全以及例子:http://www.tuicool.com/articles/ZjAfqe

上次写过一篇QWrap骨骼的文章,个人认为,想要了解一个库或框架,首先从他的核心思想入手,理解其思想,那么剩余的就仅仅是方法的堆砌。近年比较火的一个jsMVC框架backbone他的核心强依赖库为underscore

抽空提取了一下他的骨骼,其实主要就是他的链式操作的实现,别个剩下的就是具体函数的实现了,当然对于Underscore函数式也是它的最大亮点,可以好好看下函数的实现。

// Underscore骨骼
(function () {
    var root = this;
    
    
    var breaker = {};

    var ArrayProto = Array.prototype, ObjProto = Object.prototype;

    var nativeForEach    = ArrayProto.forEach,
        nativeMap        = ArrayProto.map,
        nativeFilter    = ArrayProto.filter,
        nativeKeys        = Object.keys;

    var slice            = ArrayProto.slice,
        unshift            = ArrayProto.unshift,
        hasOwnProperty  = ObjProto.hasOwnProperty;

    // 构造函数
    var _ = function (obj) { return new wrapper(obj); };

    // 向全局暴露接口
    root._ = _;

    // 类型检测
    _.isNumber = function (obj) {
        return !!(obj === 0 || (obj && obj.toExponential && obj.toFixed));
    };
    _.isFunction = function (obj) {
        return !!(obj && obj.constructor && obj.call && obj.apply);
    };

    // 遍历扩展
    var each = _.each = _.forEach = function (obj, iterator, context) {
        if (obj === null) return;
        
        if (nativeForEach && obj.forEach === nativeForEach) {
            obj.forEach(iterator, context);
        } else if (_.isNumber(obj.length)) {
            for (var i = 0, l = obj.length; i < l; i++) {
                if (iterator.call(context, obj[i], i, obj) === breaker) return; 
            }
        } else {
            for (var key in obj) {
                if (hasOwnProperty.call(obj, key)) {
                    if (iterator.call(context, obj[key], key, obj) === breaker) return; 
                } 
            }
        }
    };

    // 返回对象上面的函数名
    _.functions = _.methods = function (obj) {
        return _.filter(_.keys(obj), function (key) { return _.isFunction(obj[key])}).sort();
    };

    // 过滤数组
    _.filter = _.select = function (obj, iterator, context) {
        var results = [];
        if (obj == null) return results; 
        if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
        
        each(obj, function (value, index, list) {
            if (iterator.call(context, value, index, list)) results[results.length] = value; 
        });
        return results;
    };

    // 获取key值
    _.keys = nativeKeys || function (obj) {
        if (obj !== Object(obj)) throw new TypeError(‘Invalid object‘);
        var keys = [];
        for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key;
        return keys;
    };

    // 用于实验的map方法
    _.map = function (obj, iterator, context) {
        var results = [];
        if (obj == null) return results;
        if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
        each(obj, function (value, index, list) {
            results[results.length] = iterator.call(context, value, index, list);
        });
        return results;
    };

    // 链式操作主要部分
    var wrapper = function (obj) { this._wrapped = obj; };

    _.prototype = wrapper.prototype;

    // 扩展自定义方法到Wrap包装器上
    _.mixin = function (obj) {
        each(_.functions(obj), function (name) {
            addToWrapper(name, _[name] = obj[name]);
        });
    };
    
    // 是否对结果进行链式包装返回
    var result = function (obj, chain) {
        return chain ? _(obj).chain() : obj;
    };

    // 将方法扩展到包装器的原型上
    var addToWrapper = function (name, func) {
        wrapper.prototype[name] = function () {
            var args = slice.call(arguments);
            unshift.call(args, this._wrapped);
            return result(func.apply(_, args), this._chain);
        };
    };

    // 将所有Underscore上的方法添加到Wrap包装器上
    _.mixin(_);

    // 扩展Array上的方法到wrap包装器上-包装原数组
    each([‘pop‘, ‘push‘, ‘reverse‘, ‘shift‘, ‘sort‘, ‘splice‘, ‘unshift‘], function (name) {
        var method = ArrayProto[name];
        wrapper.prototype[name] = function () {
            method.apply(this._wrapped, arguments);
            return result(this._wrapped, this._chain);
        };
    });
    
    // 扩展Array上的方法到wrap包装器上-包装返回值
    each([‘concat‘, ‘join‘, ‘slice‘], function (name) {
        var method = ArrayProto[name];
        wrapper.prototype[name] = function () {
            return result(method.apply(this._wrapped, arguments), this._chain);
        };
    });

    // 添加链式方法的实现
    wrapper.prototype.chain = function () {
        this._chain = true;
        return this;
    };

    // 提取链式包装的内容
    wrapper.prototype.value = function () {
        return this._wrapped;
    };

})();

// 结果测试 步骤:将数组[1,2,3]进行链式包装,然后将其用val * 2来map,紧接着用filter进行val < 5过滤, 
// 然后pop,concat最后获取其值value
var re = _([1,2,3]).chain().map(function (val) {
    return val * 2;
}).filter(function (val) {
    return val < 5;
}).pop().concat([‘5‘]).value();
时间: 2024-10-09 23:10:24

Underscore骨骼的相关文章

程序员初见Maya 之 简单骨骼蒙皮动画

作为一个Unity3d程序员,和3D动画打交道的时间占了工作的大半.每天从美术手里接过热乎乎的FBX,导入到Unity3d,对其进行一番Clip切割,修改一下Scale比例,然后到代码中修改一下状态机,调试每一个动作. 但是终究是用别人的成品. FBX导入到编辑器中,看到有Root.LeftBone.Bone123456这些节点,不知道是什么东西. 这种很迷糊的感觉. 趁清明回家,花一天熟悉Maya的基础知识,做一个最简单的骨骼蒙皮动画. 开发工具: Maya2015 Unity3d 安装May

使用模块化思维和模板引擎搭建前端架构(require+underscore)

require.js 介绍: 是一个非常小巧的JavaScript模块载入框架,是AMD规范最好的实现者之一.最新版本的RequireJS压缩后只有14K,堪称非常轻量. 官网:http://www.requirejs.cn/    (PS:如果没接触过,刚开始看都是一头蒙蔽的,建议看下菜鸟教程) 新手教程:http://www.runoob.com/w3cnote/requirejs-tutorial-1.html 优点:可完成团队协作.模块复用.单元测试等等一系列复杂的需求 undersco

underscore学习总结,献给晦涩的函数式编程之美

underscore.js 越看越美,如果在项目中不断尝试underscore的方法,将会事半功倍 underscore 体现出 functionial javascript的思想,采用函数式编程的思路来解决日常生活中的一些 util的小问题 javascript 属于弱语言,对象类型用得最多的就是 array和object,underscore是基于js 封装一些对象和数组方法的库,使用起来非常便捷 这里推荐一本函数式编程的书,Functionial Javascript ,这本书对于函数式编

underscore 复习 对象函数 篇章

_.partial = function(func) { var boundArgs = slice.call(arguments, 1); var bound = function() { var position = 0, length = boundArgs.length; var args = Array(length); for (var i = 0; i < length; i++) { args[i] = boundArgs[i] === _ ? arguments[positio

javascript - Underscore 与 函数式编程

<Javascript函数式编程 PDF> # csdn下载地址http://download.csdn.net/detail/tssxm/9713727 Underscore # githubhttps://github.com/jashkenas/underscore # 中文官方网站http://www.css88.com/doc/underscore/ # CDN<script src="https://cdn.bootcss.com/underscore.js/1.8

underscore.js中的节流函数debounce及trottle

函数节流   throttle and debounce的相关总结及想法 一开始函数节流的使用场景是:放止一个按钮多次点击多次触发一个功能函数,所以做了一个clearTimeout setTimeout函数 clearTimeout(cancelTimer); cancelTimer =setTimeout(function(){ switchControl.switchAciontFactory(view, conf); },300) 代码的意思就不做多说了,实际上我无意间实现了一个debou

浅谈HTML5单页面架构(三)—— 回归本真:自定义路由 + requirejs + zepto + underscore

本文转载自:http://www.cnblogs.com/kenkofox/p/4650310.html 不过,这一篇,我想进一步探讨一下这两个框架的优缺点,另外,再进一步,抛开这两个框架,回到本真,自己搞个简单的路由一样可以实现单页面. 这个对于刚做前端开发的新同学来说就最好不过了,如果一来到岗位就一大堆angular.backbone.requirejs,看资料都看一两周.其实大家最熟悉的东西还是那个美元$,用美元能解决的问题,就不要麻烦到angular.backbone大爷了. 事先说明,

浅谈HTML5单页面架构(二)——backbone + requirejs + zepto + underscore

本文转载自:http://www.cnblogs.com/kenkofox/p/4648472.html 上一篇<浅谈HTML5单页面架构(一)——requirejs + angular + angular-route>探讨了angular+requirejs的一个简单架构,这一篇继续来看看backbone如何跟requirejs结合. 相同地,项目架构好与坏不是说用了多少牛逼的框架,而是怎么合理利用框架,让项目开发更流畅,代码更容易管理.那么带着这个目的,我们来继续探讨backbone. 首

underscore中文api (1.8.2)

Underscore一个JavaScript实用库,提供了一整套函数式编程的实用功能,但是没有扩展任何JavaScript内置对象.它是这个问题的答案:“如果我在一个空白的HTML页面前坐下, 并希望立即开始工作, 我需要什么?“...它弥补了部分jQuery没有实现的功能,同时又是Backbone.js必不可少的部分. (感谢@小邓子daj的翻译建议) Underscore提供了100多个函数,包括常用的: map, filter, invoke — 当然还有更多专业的辅助函数,如:函数绑定,