最近在拜读只有1700行(含注释)代码的Underscore.js 1.9.1,记录一些东西

(参考https://underscorejs.org/underscore.jshttps://github.com/hanzichi/underscore-analysis

  1. void 0替代了undefined;因为在低版本ie中undefined可以被重新赋值,或者在局部作用域中也可以被重新赋值;所以undefined显得不那么靠谱,于是就用void 0替代了undefined,void运算符对表达式求值都会返回undefined;
  2. 数据类型判断,先看原声方法支持与否,不支持再用Object.prototype.toString.call方法进行判断;不过在 IE < 9 下对 arguments 调用 Object.prototype.toString.call,结果是 [object Object],这时可以用arguments.callee是否存在来判断;dom元素判断方法为存在且nodeType为1;
  3. 如果在对象中重写了原型上的不可枚举属性,那么for in是可以取到这个属性的;但是在低版本ie中是不会取到的,它们会被认定为不可枚举属性;可以用obj.propertyIsEnumerable(prop)来确定对象中指定的属性是否可以被for in循环枚举,但是通过原型链继承的属性除外;
  4. createAssigner(补)
  5. 判断是否相同(注意0 === -0,但不相同)
    /* 1 */
    if (a === b) return a !== 0 || 1 / a === 1 / b; /* 2 null undefined */
    if (a == null || b == null) return false; /* 3 NaN */
    if (a !== a) return b !== b; /* 4 primitive */
    var type = typeof a;
    if (type !== 'function' && type !== 'object' && typeof b != 'object') return false; /* 5 正则 和 String */
    return '' + a === '' + b; /* 6 Number */
    if (+a !== +a) return +b !== +b;
    return +a === 0 ? 1 / +a === 1 / b : +a === +b; /* 7 Date Boolean */
    return +a === +b; /* 8 Symbol */
    var SymbolProto = typeof Symbol !== 'undefined' ? Symbol.prototype : null;
    return SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b);
  6. Object Functions(补)

  7. 位运算符&换算成二进制后按位与计算;不同于&&;
    // 判断偶数
    var isEven = function(num) {
    return !(num & 1);
    };
  8. 数组去重

    /* 1 一一比较 */
    function removeSame(arr){
    return arr.filter(function(item, index, arr){
    return arr.indexOf(item) === index;
    });
    } /* 2 */
    [...new Set(arr)] /* 3 */
    Array.from(new Set(arr));
  9. flatten
    // shallow为false深度展开,当shallow strict都为true可忽略非数组元素
    
    var flatten = function(input, shallow, strict, output) {
    output = output || [];
    var idx = output.length;
    for (var i = 0, length = getLength(input); i < length; i++) {
    var value = input[i];
    if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
    if (shallow) {
    var j = 0, len = value.length;
    while (j < len) output[idx++] = value[j++];
    } else {
    flatten(value, shallow, strict, output);
    idx = output.length;
    }
    } else if (!strict) {
    output[idx++] = value;
    }
    }
    return output;
    };
  10. _.compact _.difference  _.without(补)

  11. NaN和Number.NaN是一样的;只有Number.isNaN(NaN)才返回true,isNaN()会将参数现转换为数字类型;
    isNaN = function(obj) {
    Number.isNaN(Number(obj));
    } Number.isNaN = Number.isNaN || function(obj) {
    return typeof obj === "number" && isNaN(obj);
    } _.isNaN = function(obj) {
    return _.isNumber(obj) && isNaN(obj);
    };
  12. 类数组转为数组
    Array.prototype.slice.call(obj) 或 Array.from(obj)
    // 优化(传递arguments给任何参数,将导致Chrome和Node中使用的V8引擎跳过对其的优化,这也将使性能相当慢)
    
    var args = new Array(arguments.length);
    for(var i = 0; i < args.length; ++i) {
    args[i] = arguments[i];
    }
  13. 数组乱序
    /* 1 O(n^2)*/
    function shuffle(arr) {
    var result = [];
    while (arr.length) {
    var index = ~~(Math.random() * arr.length); // 两次按位取反,无论正负,去掉小数点后面的数
    result.push(arr[index]);
    arr.splice(index, 1);
    }
    return result;
    } /* 2 O(nlogn)*/
    function shuffle(arr) {
    return arr.sort(function(a, b) {
    return Math.random() - 0.5;
    });
    } /* 3 Fisher–Yates Shuffle 遍历数组 将其与之前的元素交换 O(n)*/
    function shuffle(arr){
    var len = arr.length;
    var shuffled = Array(len);
    for(var i=0, rand; i < len; i++){
    rand = ~~(Math.random()*(i+1));
    if(rand !== i){
    shuffled[i] = shuffled[rand];
    }
    shuffled[rand] = arr[i];
    }
    return shuffled;
    }
  14. Group(补)
  15. bind polyfill
    if (!Function.prototype.bind) {
    Function.prototype.bind = function(oThis) {
    if (typeof this !== 'function') {
    // closest thing possible to the ECMAScript 5
    // internal IsCallable function
    throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }
    var aArgs = Array.prototype.slice.call(arguments, 1),
    fToBind = this,
    fNOP = function() {},
    fBound = function() {
    return fToBind.apply(this instanceof fNOP
    ? this
    : oThis,
    // 获取调用时(fBound)的传参.bind 返回的函数入参往往是这么传递的
    aArgs.concat(Array.prototype.slice.call(arguments)));
    };
    // 维护原型关系
    if (this.prototype) {
    // Function.prototype doesn't have a prototype property
    fNOP.prototype = this.prototype;
    }
    fBound.prototype = new fNOP();
    return fBound;
    };
    }
  16. 节流
    _.throttle = function(func, wait, options) {
    var timeout, context, args, result;
    var previous = 0;
    if (!options) options = {}; var later = function() {
    previous = options.leading === false ? 0 : _.now();
    timeout = null;
    result = func.apply(context, args);
    if (!timeout) context = args = null;
    }; var throttled = function() {
    var now = _.now();
    if (!previous && options.leading === false) previous = now;
    var remaining = wait - (now - previous);
    context = this;
    args = arguments;
    if (remaining <= 0 || remaining > wait) {
    if (timeout) {
    clearTimeout(timeout);
    timeout = null;
    }
    previous = now;
    result = func.apply(context, args);
    if (!timeout) context = args = null;
    } else if (!timeout && options.trailing !== false) {
    timeout = setTimeout(later, remaining);
    }
    return result;
    }; throttled.cancel = function() {
    clearTimeout(timeout);
    previous = 0;
    timeout = context = args = null;
    }; return throttled;
    };
  17. 防抖
     _.debounce = function(func, wait, immediate) {
    var timeout, result; var later = function(context, args) {
    timeout = null;
    if (args) result = func.apply(context, args);
    }; var debounced = restArguments(function(args) {
    if (timeout) clearTimeout(timeout);
    if (immediate) {
    var callNow = !timeout;
    timeout = setTimeout(later, wait);
    if (callNow) result = func.apply(this, args);
    } else {
    timeout = _.delay(later, wait, this, args);
    } return result;
    }); debounced.cancel = function() {
    clearTimeout(timeout);
    timeout = null;
    }; return debounced;
    };

读underscore的更多相关文章

  1. underscore源码阅读记录

    这几天有大神推荐读underscore源码,趁着项目测试的空白时间,看了一下. 整个underscore包括了常用的工具函数,下面以1.3.3源码为例分析一下. _.size = function(o ...

  2. 有哪些值得一读的优秀开源 JS 代码

    有哪些值得一读的优秀开源 JS 代码 采纳 首先,没有“必须”读的源代码(我发现我特喜欢说首先……),因为读源代码不是做功课,只有用到或是非常好奇才会去读,当成“日常”去做是没有意义的. 当然有些人会 ...

  3. underscore 源码解读之 bind 方法的实现

    自从进入七月以来,我的 underscore 源码解读系列 更新缓慢,再这样下去,今年更完的目标似乎要落空,赶紧写一篇压压惊. 前文 跟大家简单介绍了下 ES5 中的 bind 方法以及使用场景(没读 ...

  4. UnderScore源代码阅读1

    读一下underscore源代码,用于自己学习,个人理解,如果有不对的地方希望指正,谢谢 我觉着阅读的顺序按照从整体到局部,从架构到细节较好. 1.整体架构 (function() {}.call(t ...

  5. 一次发现underscore源码bug的经历以及对学术界『拿来主义』的思考

    事情是如何发生的 最近干了件事情,发现了 underscore 源码的一个 bug.这件事本身并没有什么可说的,但是过程值得我们深思,记录如下,各位看官仁者见仁智者见智. 平时有浏览园区首页文章的习惯 ...

  6. 停止使用循环 教你用underscore优雅的写代码

    你一天(一周)内写了多少个循环了? var i; for(i = 0; i < someArray.length; i++) {   var someThing = someArray[i]; ...

  7. `~!$^*()[]{}\|;:'",<>/?在英文怎么读?

    `~!$^*()[]{}\|;:'",<>/?在英文怎么读? 'exclam'='!' 'at'='@' 'numbersign'='#' 'dollar'='$' 'perce ...

  8. underscore.js源码解析(一)

    一直想针对一个框架的源码好好的学习一下编程思想和技巧,提高一下自己的水平,但是看过一些框架的源码,都感觉看的莫名其妙,看不太懂,最后找到这个underscore.js由于这个比较简短,一千多行,而且读 ...

  9. underscore.js源码解析(五)—— 完结篇

    最近公司各种上线,所以回家略感疲惫就懒得写了,这次我准备把剩下的所有方法全部分析完,可能篇幅过长...那么废话不多说让我们进入正题. 没看过前几篇的可以猛戳这里: underscore.js源码解析( ...

随机推荐

  1. onethink插件控制器如何访问?

    具体路由分析就不说啦!就是那样.这里我只是方便访问来做一个记录,方便复制粘贴访问: 例如:新增一个Baoming的插件: 那么如何,访问这个控制里面方法呢? 第一种情况:这个控制器使用的是Admin模 ...

  2. R中的各种概率统计分布

    名称 名称 R对应的名字 附加参数 β分布 beta beta shape1, shape2, ncp 二项式分布 binomial binom size, prob 柯西分布 Cauchy cauc ...

  3. 170713、springboot编程之多数据源切换

    我们在开发过程中可能需要用到多个数据源,我们有一个项目(MySQL)就是和别的项目(SQL Server)混合使用了.其中SQL Server是别的公司开发的,有些基本数据需要从他们平台进行调取,那么 ...

  4. mysql中sql注入的随笔

    当使用如下登录代码时:就会引发sql注入问题 怎么注入呢? 'or 1=1 # 就可以了. 为什么呢? 首先or:在sql中是或者,只要满足前一个或后一个条件即可,只要所以不论你是 'or 1=1 # ...

  5. MySQL Bugs: #34354: Feature request: EXPLAIN ALTER TABLE https://bugs.mysql.com/bug.php?id=34354

    MySQL Bugs: #34354: Feature request: EXPLAIN ALTER TABLE https://bugs.mysql.com/bug.php?id=34354 [SQ ...

  6. MyBatis 内置日志工厂基于运行时自省机制选择合适的日志工具

    mybatis – MyBatis 3 | 日志 http://www.mybatis.org/mybatis-3/zh/logging.html MyBatis 内置日志工厂基于运行时自省机制选择合 ...

  7. Android-aidl, binder,surfaceview

    http://blog.csdn.net/stonecao/article/details/6425019 http://www.cnblogs.com/linucos/archive/2012/05 ...

  8. kafka集群与zookeeper集群 配置过程

    Kafka的集群配置一般有三种方法,即 (1)Single node – single broker集群: (2)Single node – multiple broker集群:    (3)Mult ...

  9. Antenna Placement---poj3020(最大匹配)

    题目链接:http://poj.org/problem?id=3020 题意:每个 ‘*’都需要一个1*2的东西覆盖,问最少需要多少个1*2的东西来覆盖这些‘*’ 和Oil Skimming的题解几乎 ...

  10. const V.S readonly

    先上两个例子: ; ; static void Main(string[] args) { Console.WriteLine("A is {0},B is {1}", A, B) ...