underscore.js 解读(敲源码)

本文介绍了underscore.js作为一个JavaScript实用库的特点和功能,重点探讨了如何避免作用域污染的问题。作者分享了自己在GitHub上的源码实现,并提到了与jQuery的对比。还列举了一些underscore中重要的功能函数,鼓励读者通过敲源码来深入学习。
摘要由CSDN通过智能技术生成

我把第一遍敲的underscore的代码放在github上了,加上了备注和一些demo 感兴趣的可以去看看。
https://github.com/katoto/copyUnderscore

还有一个是和jQuery 相关的,也可以敲敲看。
https://github.com/katoto/Tur_jq

Underscore一个JavaScript实用库,提供了一整套函数式编程的实用功能。正因为如此,所以它的每一个方法都相对独立。适合初学者敲一敲,也可以学习学习。下面我将贴一些,自己认为比较重要的函数。

undersocre 如何避免作用域污染?

;(function(){
    var root = this;
    var previousUnderscore = root._;
    var Ctor = function(){};    
    var _= function(obj){                  //  ☆
        if(obj instanceof _)return obj;
        if(!(this instanceof _))return new _(obj);
        this._wrapped = obj;
    };  
        //          释放 _ 的控制权 要在_ 声明的后面
    _.noConflict = function(){
        root._ = previousUnderscore;
        return this;
    }
    if(typeof exports !== 'undefined'){
        if(typeof module !== 'undefined'&& module.exports){
            exports = module.exports = _;
        }
        exports._  = _;
    }else{
        root._ = _;
    }
    _.VERSION ='0.01'
//          传入全局变量 window or node
}.call(this))

jQuery如何避免作用域污染?

;(function(window ,undefined){
//Tur_jq 构造函数    定义undefined 是为了兼容性
    var Tur_jq = function Tur_jq ( selector ){
      return new Tur_jq.prototype.init( selector );
    };
    Tur_jq.fn = Tur_jq.prototype = {
        constructor:Tur_jq,
        selector:null,
        length:0,
        version:0.01,
       init:function( selector ) {
           //是空的和undefined 直接返回
           if (!selector) return this;
           // 字符串:选择器,html
           if (Tur_jq.isString(selector)) {
               if (selector.charAt(0) === '<') {
                   Tur_jq.push.apply(this, Tur_jq.parseHTML(selector));
               } else {
                   Tur_jq.push.apply(this, Tur_jq.select(selector));
                   this.selector = selector;
               }
               return this;
           }
           //DOM 对象
           if (Tur_jq.isDOM( selector )){
               this[0] = selector;
               this.length =1;
               return this;
           }
           //Tur_jq 对象
           if( Tur_jq.isTur_jq( selector )){
               return selector;
           }
           // DOM 数组
           if( Tur_jq.isLikeArray( selector )){
               Tur_jq.push.apply( this ,selector );
               return this;
           }
           // 如果是函数的话 就是入口函数
           if( Tur_jq.isFunction( selector ) ){
               var oldFn = window.onload;
               if( typeof oldFn ==='function' ){
                   window.onload = function(){
                       oldFn();
                       selector();
                   };
               }else {
                   window.onload = selector;
               }
           }
       },
        each:function( callback  ){
            Tur_jq.each( this ,callback );
            return this;
        }
    };
    Tur_jq.fn.init.prototype = Tur_jq.prototype;
    //可扩展
    Tur_jq.extend = Tur_jq.fn.extend = function( obj ){
      var k ;
        for( k in obj  ){
            this[k] = obj [k];
        }
    };
//  比如你要扩展函数
    Tur_jq.extend({
       isFunction:function(obj){
           return typeof obj === 'function';
       },
        isString:function( obj ){
            return typeof  obj ==='string';
        },
        isLikeArray: function( obj ){
            return obj && obj.length && obj.length >=0;
        },
        isTur_jq:function( obj ){
            return 'selector' in obj;
        },
        isDOM:function( obj ){
            return !!obj.nodeType;
        }
    });
//  同理就一直往下.....
    // 对外公开
    window.$ = window.jQurey = Tur_jq;
})( window );

underscore 对内置函数的处理

//实现更少的字节和作用域链查找   (可以再浏览数上看原型上有什么内置的方法)
        var ArrayProto = Array.prototype,
            ObjProto = Object.prototype,
            FuncProto = Function.prototype;
        var push = ArrayProto.push,
            slice = ArrayProto.slice,
            toString = ObjProto.toString,
            hasOwnProperty = ObjProto.hasOwnProperty;
//      ECMAScript 5 的原生方法  keys? bind?
        var nativeIsArray = Array.isArray,
            nativeKeys = Object.keys,
            nativeBind = FuncProto.bind,
            nativeCreate = Object.create;

而jQuery 一开始就会对当前的浏览器进行能力检测的。
下面贴一些 我认为很好的功能函数(有依赖,去看看源码就懂了)

//          洗牌算法       ☆
        _.shuffle = function(obj){
            var set = isArrayLike(obj)?obj:_.values(obj);
            var length = set.length,
                shuffled = Array(length);
                for(var index=0,rand;index<length;index++){
                    rand = _.random(0,index);
                    if(rand !== index) shuffled[index]=shuffled[rand];
                    shuffled[rand]= set[index];
                }
                return shuffled;
        };
//      判断是否是isArray     ☆
        _.isArray = nativeIsArray || function(obj){
            return toString.call(obj) ==='[object Array]';
        }
//机智写法
_.each(['Arguments','Function','String','Number','Date','RegExp','Error'],function(name){
            _['is'+name]= function(obj){
                return toString.call(obj)=== '[object '+name+']' ;
            };
        });
//      ☆    nodeType 来判断   
        _.isElement = function(obj){
            return !!(obj && obj.nodeType ===1 );
        };
        _.isObject = function(obj){
            var type = typeof obj;
            //  0 || 1&& 1   1    0 || 1&& 0   0    
            return type ==='function'|| type==='object'&& !!obj
        }
//      !!!!  模板字符串           得认真看看才行
        _.templateSetting = {
            evaluate :/<%([\s\S]+?)%>/g,
            interpolate:/<%=([\s\S]+?)%>/g,
            escape :/<%-([\s\S]+?)%>/g
        };

        var noMatch = /(.)^/;
        var escapes = {
            "'":"'",
            '\\':'\\',
            '\r':'r',
            '\n':'n',
            '\u2028':'u2028',
            '\u2029':'u2029'
        };

        var escapeChar = function(match){
            return '\\'+escapes[match];
        }

        _.template = function(text,settings,oldSettings){
            if(!settings && oldSettings)settings = oldSettings;
            settings = _.defaults({},settings,_.templateSettings);

            var matcher = RegExp([
                (settings.escape || noMatch).source,
                (settings.interpolate|| noMatch).source,
                (settings.evaluate || noMatch).source
            ].join('|')+'|$','g');

            var index = 0;
            var source = "__p+='";
            text.replace(matcher,function(match,escape,interpolate,evaluate,offset){
                source += text.slice(index,offset).replace(escaper,escapeChar);
                index = offset + match.length;

                if(escape){
                    source +="'+\n((__t("+escape+"))==null?'':_.escape(__t))+\n'";
                }else if(interpolate){
                    source +="'+\n((__t=("+interpolate+"))==null?'':__t)+\n'";
                }else if(evaluate){
                    source +="';\n"+evaluate+"\n__p+='";
                }
                return match;
            })

            if(!settings.variable)source = 'with(obj||{}){\n'+source+'\n}';

            source = "var __t,__p='',__j=Array.prototype.join,"+
                    "print=function(){__p+=__j.call(arguments,'');};\n"+
                    source +'return __p;\n';

            try{
                var render = new Function(settings.variable || 'obj','_',source);
            }catch(e){
                e.source = source;
                throw e;
            }
            var template = function(data){
                return render.call(this,data,_);
            };
            var argument = settings.variable || 'obj';
            template.source = 'function('+argument+'){\n'+source+'}';

            return template;            
        }
//      Object.prototype.toString.call(2) // "[object Number]"
//      Object.prototype.toString.call('') // "[object String]"
//      Object.prototype.toString.call(true) // "[object Boolean]"
//      Object.prototype.toString.call(undefined) // "[object Undefined]"
//      Object.prototype.toString.call(null) // "[object Null]"
//      Object.prototype.toString.call(Math) // "[object Math]"
//      Object.prototype.toString.call({}) // "[object Object]"
//      Object.prototype.toString.call([]) // "[object Array]"

本想写的更好一点的,不过实在不懂如何下手,感觉也没人看,就算了。

underscore 里有个template 详细的可以查看这篇博客:

http://blog.csdn.net/fendouzhe123/article/details/39083367

详情可查看:
http://www.css88.com/doc/underscore/

阮一峰资料:
http://javascript.ruanyifeng.com/library/underscore.html

end 更多请敲源码!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值