• 读underscore


    最近在拜读只有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;
        };
  • 相关阅读:
    vagrant 的安装与使用
    vagrant 的安装与使用
    rz、sz (上传下载)命令参数的解释
    rz、sz (上传下载)命令参数的解释
    TensorFlow 学习(十五)—— tensorflow.python.platform
    音乐的作曲形式
    vc中edit控件使用总结
    引用 LPSTR、LPCSTR、LPTSTR、LPCTSTR、LPWSTR及LPCWSTR的意义及区别
    编译原理三大经典书籍(龙书 虎书 鲸书)
    VS2003与Win7的兼容性问题
  • 原文地址:https://www.cnblogs.com/colima/p/9192309.html
Copyright © 2020-2023  润新知