// 1. 不污染全局环境
(function() { // 2. 保留之前同名变量
var previousUnderscore = window._; var _ = function(obj) {
return new wrapper(obj);
}; // 模块化
if (typeof define === 'function' && define.amd) {
define('underscore', [], function() {
return _;
});
} else if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = _;
}
exports._ = _;
} else {
window['_'] = _;
} // 3. undersocre链式方案
var wrapper = function(obj) {
this._wrapped = obj;
}; // 链式包装函数
var result = function(obj, chain) {
return chain ? _(obj).chain() : obj;
}; // 触发可链式函数
wrapper.prototype.chain = function() {
// this._chain用来标示当前对象是否使用链式操作
this._chain = true;
return this;
}; // 当触发可链式后,用这个来取结果值
wrapper.prototype.value = function() {
return this._wrapped;
}; // 4.将_的静态方法,赋值给_对象
var ArrayProto = Array.prototype,
forEach = ArrayProto.forEach,
push = ArrayProto.push;
_.each = forEach; _.type = function(obj){
return Object.prototype.toString.call(obj).slice(8,-1).toLowerCase();
} _.isFunction = function(fn){
return (_.type(fn) == "function");
} _.functions = function(obj) {
var names = [];
for (var key in obj) {
if (_.isFunction(obj[key])) names.push(key);
}
return names.sort();
} _.mixin = function(obj) {
forEach.call(_.functions(obj), function(name) {
var func = _[name] = obj[name];
_.prototype[name] = function() {
var args = [this._wrapped];
push.apply(args, arguments);
return result( func.apply(_, args),this._chain);
};
});
}; // _是返回wrapper的实例,该实例没有_.protoype的方法
// 所以把 _.prototype 指向了 wrapper.prototype,
// 之后往_.prototype添函数,也就是向wrapper.prototype添函数
_.prototype = wrapper.prototype;
_.prototype.constructor = _;
_.mixin(_); // 5.扩展_对象的方法
// 这些数组方法本身不可链式
forEach.call(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { var method = ArrayProto[name];
wrapper.prototype[name] = function() {
var wrapped = this._wrapped;
// 调用Array对应的方法并返回结果
method.apply(wrapped, arguments);
var length = wrapped.length;
if ((name == 'shift' || name == 'splice') && length === 0) {
delete wrapped[0];
}
return result(wrapped, this._chain);
};
}); // 这些数组方法本身可链式
forEach.call(['concat', 'join', 'slice'], function(name) {
var method = ArrayProto[name];
wrapper.prototype[name] = function() {
return result(method.apply(this._wrapped, arguments), this._chain);
};
}); })(); // 使用实例 // 不可链式方法,使其可链式
// var errorTest = [1,2].push(3).push(4); // push这个函数返回的是函数长度,所以这里会报错
var underscore_obj = _([1, 2]).chain().push(3).push(4);
var result_arr = underscore_obj.value();
console.log(result_arr);

underscore的封装和扩展的更多相关文章

  1. 一步一步学习underscore的封装和扩展方式

    前言 underscore虽然有点过时,这些年要慢慢被Lodash给淘汰或合并. 但通过看它的源码,还是能学到一个库的封装和扩展方式. 第一步,不污染全局环境. ES5中的JS作用域是函数作用域. 函 ...

  2. 【转】Python基础-封装与扩展、静态方法和类方法

    [转]Python基础-封装与扩展.静态方法和类方法 一.封装与扩展 封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码:而外部使用者只知道一个接口(函数),只要接口(函数 ...

  3. Python基础-封装与扩展、静态方法和类方法

    一.封装与扩展 封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码:而外部使用者只知道一个接口(函数),只要接口(函数)名.参数不变,使用者的代码永远无需改变.这就提供一个 ...

  4. 玩转控件:对Dev中GridControl控件的封装和扩展

    又是一年清明节至,细雨绵绵犹如泪光,树叶随风摆动.... 转眼间,一年又过去了三分之一,疫情的严峻让不少企业就跟清明时节的树叶一样,摇摇欲坠.裁员的裁员,降薪的降薪,996的996~~说起来都是泪,以 ...

  5. Delphi对于控件的SuperClassing(封装并扩展Button,使之变成TButton)

    写博客写了这么久,但是一直不知道应该怎么样写函数之间的调用关系和执行顺序,因为不停的跳来跳去的,但是写的时候却只能顺序写调用关系,直到今天发现这种写法很不错: TButton创建窗口是在CreateW ...

  6. jQuery的封装和扩展方式

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  7. 对bootstrap modal的简单扩展封装

    对bootstrap modal的简单扩展封装 参考自:http://www.muzilei.com/archives/677   注:原文不支持bootstrap新版本,并且居中等存在问题 此段时间 ...

  8. SwiftyUserDefaults对NSUserDefaults的封装扩展

    SwiftyUserDefaults 是对NSUserDefaults的一些封装和扩展,这个库这个只有一个类,操作起来十分简单方便: 这里只有两个步骤来使用SwiftyUserDefaults: st ...

  9. underscore源码解析 (转载)

    转载出自http://www.cnblogs.com/human/p/3273616.html (function() { // 创建一个全局对象, 在浏览器中表示为window对象, 在Node.j ...

随机推荐

  1. ubuntu 修改终端命令显示的颜色

    转于  http://www.blogbus.com/riusksk-logs/62891140.html 修改当前用户 gedit ~/.bashrc 在最后一行下面添加这行 PS1='${debi ...

  2. 5.24 Declaring Attributes of Functions【转】

    转自:https://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Function-Attributes.html 5.24 Declaring Attributes o ...

  3. jenkins+jmeter+ant搭建接口测试平台

    接口测试的重点是检查数据的交换,传递和控制管理过程以及系统间的相互逻辑依赖关系. 接口测试的流程 项目启动后,测试人员要尽早拿到接口测试文档. 开始编写接口测试用例 将接口测试用例部署到持续集成的测试 ...

  4. Verilog HDL基础语法讲解之模块代码基本结构

    Verilog HDL基础语法讲解之模块代码基本结构   本章主要讲解Verilog基础语法的内容,文章以一个最简单的例子"二选一多路器"来引入一个最简单的Verilog设计文件的 ...

  5. Linux下Nagios的安装与配置

    一.本文说明 本文是在参考:http://www.cnblogs.com/mchina/archive/2013/02/20/2883404.html   David_Tang文章以及网上的一些资料完 ...

  6. HDU 1498:50 years, 50 colors(二分图匹配)

    http://acm.hdu.edu.cn/showproblem.php?pid=1498 题意:给出一个 n*n 的矩阵,里面的数字代表一种颜色,每次能炸掉一排或者一列的相同颜色的气球,问有哪些颜 ...

  7. ACM题目————字串数

    Description 一个A和两个B一共可以组成三种字符串:"ABB","BAB","BBA". 给定若干字母和它们相应的个数,计算一共可 ...

  8. ACM题目————Find them, Catch them

    Description The police office in Tadu City decides to say ends to the chaos, as launch actions to ro ...

  9. 杭电1002-A + B Problem II

    #include<stdio.h>#include<string.h> int main(){    char str1[1001],str2[1001];    int t, ...

  10. 20150612_Andriod contextual action mode 菜单

    参考地址:http://www.xuebuyuan.com/1114028.html              http://www.cnblogs.com/mengdd/p/3564782.html ...