underscore.js 解读(敲源码)
2016-11-20 22:51
501 查看
我把第一遍敲的underscore的代码放在github上了,加上了备注和一些demo 感兴趣的可以去看看。
https://github.com/katoto/copyUnderscore
还有一个是和jQuery 相关的,也可以敲敲看。
https://github.com/katoto/Tur_jq
Underscore一个JavaScript实用库,提供了一整套函数式编程的实用功能。正因为如此,所以它的每一个方法都相对独立。适合初学者敲一敲,也可以学习学习。下面我将贴一些,自己认为比较重要的函数。
undersocre 如何避免作用域污染?
jQuery如何避免作用域污染?
underscore 对内置函数的处理
而jQuery 一开始就会对当前的浏览器进行能力检测的。
下面贴一些 我认为很好的功能函数(有依赖,去看看源码就懂了)
本想写的更好一点的,不过实在不懂如何下手,感觉也没人看,就算了。
underscore 里有个template 详细的可以查看这篇博客:
http://blog.csdn.net/fendouzhe123/article/details/39083367
详情可查看:
http://www.css88.com/doc/underscore/
阮一峰资料:
http://javascript.ruanyifeng.com/library/underscore.html
end 更多请敲源码!
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 更多请敲源码!
相关文章推荐
- JS判断元素为数字的奇异写法分享 这是在阅读underscore(1.3.3)源码中看到的,它的each方法
- underscore.js 源码中一些实用的工具方法
- underscore.js源码解析之函数绑定
- Underscore.js 1.3.3 源码分析收藏
- Underscore.js 1.3.3 源码分析收藏
- underscore.js 源码之 数组展开和数组去重
- underscore.js 源码分析5 基础函数和each函数的使用
- underscore.js源码解析【对象】
- underscore.js源码解析【'_'对象定义及内部函数】
- 【第三方类库】underscore.js源码---each forEach 每次迭代跟{}比较的疑惑
- underscore.js 源码
- underscore.js源码解析【数组】
- underscore.js源码解析【函数】
- underscore.js源码解析之类型判断
- underscore.js源码学习——_.template()
- underscore.js源码解析【集合】
- underscore.js源码解析之命名空间
- Underscore.js源码分析(一)
- JS中判断相等的方法(underscore中eq方法源码分析)
- underscorejs 源码走读笔记