您的位置:首页 > Web前端 > JavaScript

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 如何避免作用域污染?

;(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 更多请敲源码!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript 源码