博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Underscore骨骼
阅读量:4490 次
发布时间:2019-06-08

本文共 4175 字,大约阅读时间需要 13 分钟。

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

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

<!
DOCTYPE html
>
<
html
>
<
head
>
<
title
>
 Underscore骨骼 
<
/
title>
<
/
head>
<
body
>
<
script type
=
"
text/javascript
"
>
//
 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();
alert(re);
<
/
script>
<
/
body> 

< /html>

转载于:https://www.cnblogs.com/bluedream2009/archive/2011/07/02/2096309.html

你可能感兴趣的文章
为什么要应用编排,应用编排能做什么?
查看>>
实习生招聘笔试
查看>>
Linux忘记root登录密码解决方法
查看>>
String类的常用方法
查看>>
week 13 java——网络
查看>>
python curl实现
查看>>
C/C++ http协议加载sessionID
查看>>
个人应用开发详记. (二)
查看>>
一款由css3和jquery实现的卡面折叠式菜单
查看>>
uva 10791
查看>>
openlayers 4快速渲染管网模型数据
查看>>
MySQL相关小技巧
查看>>
SSH整合-&nbsp;2-&nbsp;add&nbsp;service&nbsp;layout
查看>>
IP地址与UInt之间不得不说的故事
查看>>
【代码笔记】iOS-两个滚动条,上下都能滑动
查看>>
矩阵乘法-洛谷P2233 [HNOI2002] 公交车路线
查看>>
openstack云主机硬盘复制查询
查看>>
写个神经网络,让她认得我`(๑•ᴗ•๑)(Tensorflow,opencv,dlib,cnn,人脸识别)
查看>>
《程序是怎样跑起来的》第三章
查看>>
Jquery回到顶部效果
查看>>