XFE 技术 生活 文集

javascript代码片段

🔖 javascript 👀 25 🕒 2018-07-03

持续积累中~

拓展原型

Function.prototype.method = function(name, extend) {
  if(!this.prototype[name]) {
    this.prototype[name] = extend;
  }
  return this;
}

实现继承·方法1

Function.method("inherits", function(Parent) {
  var _proptotype = Object.create(Parent.prototype);
  _proptotype.constructor = this.prototype.constructor;
  this.prototype = _proptotype;
  return this;
})

实现继承·方法2

function inherits(child, parent) {
    var _proptotype = Object.create(parent.prototype);
    _proptotype.constructor = child.prototype.constructor;
    child.prototype = _proptotype;
    return {
        "child": child,
        "parent": parent
    };
}

实现继承·方法3

//只创建临时构造函数一次
var inherit = (function () {
    var F = function () {};
    return function (C, P) {
        F.prototype = P.prototype;
        C.prototype = new F();
        C.uber = P.prototype;            // 存储超类
        C.prototype.constructor = C;     // 重置构造函数指针
   }
})();

浅拷贝

function simpleCopy() {
    var c = {};
    for(var i in p) {
        c[i] = p[i];
    }
    return c;
}

深拷贝

function deepCopy(p, c) {
    var c = c || {};
    for(var i in p) {
        if(typeof p[i] === 'object') {
            c[i] = (p[i].constructor === Array) ? [] : {};
            deepCopy(p[i], c[i]);
        } else {
            c[i] = p[i];
        }
    }
    return c;
}

带特性值的浅拷贝

function Composition(target, source){
    var desc = Object.getOwnPropertyDescriptor;
    var prop = Object.getOwnPropertyNames;
    var def_prop=Object.defineProperty;
    prop(source).forEach(function(key) {
        def_prop(target, keydesc(source, key))
    })
    return target;
}

mixin混合

function mix() {
    var arg, prop, child = {};
        for(arg = 0; arg < arguments.length; arg += 1) {
            for(prop in arguments[arg]) {
                if(arguments[arg].hasOwnProperty(prop)) {
                    child[prop] = arguments[arg][prop];
                }
            }
        }
        return child;
}

对象拓展

var MYAPP = MYAPP || {};
MYAPP.namespace = function(ns_string) {
    var parts = ns_string.split('.'),
        parent = MYAPP,
        i;
    //忽略第一个
    if(parts[0] === "MYAPP") {
        parts = parts.slice(1);
    }
    for(i = 0; i < parts.length; i += 1) {
        //如果属性不存在,就创建
        if(typeof parent[parts[i]] === "undefined") {
            parent[parts[i]] = {};
        }
        parent = parent[parts[i]];
    }
    return parent;
};
MYAPP.namespace('once.upon.a.time.there.was.this.long.nested.property');

函数柯里化

function curry(fn){
    var args = Array.prototype.slice.call(arguments, 1);
    return function(){
         var innerArgs = Array.prototype.slice.call(arguments);
         var finalArgs = args.concat(innerArgs);
         return fn.apply(null, finalArgs);
    };
}
function add(num1, num2){
    return num1 + num2;
}
var curriedAdd = curry(add, 5);
alert(curriedAdd(3)); //8

跨文件共享私有对象·模块互访

var blogModule = (function(my) {
    var _private = my._private = my._private || {},
    _seal = my._seal = my._seal || function() {
        delete my._private;
        delete my._seal;
        delete my._unseal;
    },
    _unseal = my._unseal = my._unseal || function() {
        my._private = _private;
        my._seal = _seal;
        my._unseal = _unseal;
    };
    return my;
}(obj || {}));

类型判断

function isType(val, type) {
    val = Object.prototype.toString.call(val).toLowerCase();
    if(typeof(type) === "string") {
        return val === '[object ' + type.toLowerCase() + ']';
    }
    return val.replace(/(\[object\s)|(\])/g, "");
}

软绑定·默认绑定可设置

Function.prototype.softBind = function(obj) {
    var fn = this;
    // 捕获所有 curried 参数
    var curried = [].slice.call( arguments, 1 );
    var bound = function() {
          return fn.apply(
                (!this || this === (window || global)) ?
                     obj : this
                curried.concat.apply( curried, arguments )
          );
    };
    bound.prototype = Object.create( fn.prototype );
    return bound;
};

函数节流

function throttle(fn, wait){
    var timer;
    return function(...args){
      if(!timer){
          timer = setTimeout(()=>timer=null, wait);
          return fn.apply(this, args);
      }
    }
}

函数防抖

function debounce(fn, delay){
    var timer = null;
    return function(...args){
        clearTimeout(timer);
        timer = setTimeout(() => fn.apply(this, args), delay);
    }
}

js精度运算

var floatObj = function() {

    // 判断obj是否为一个整数
    function isInteger(obj) {
        return Math.floor(obj) === obj
    }

    /*
     * 将一个浮点数转成整数,返回整数和倍数。如 3.14 >> 314,倍数是 100
     * @param floatNum {number} 小数
     * @return {object}
     *   {times:100, num: 314}
     */
    function toInteger(floatNum) {
        var ret = {times: 1, num: 0}
        var isNegative = floatNum < 0
        if (isInteger(floatNum)) {
            ret.num = floatNum
            return ret
        }
        var strfi  = floatNum + ''
        var dotPos = strfi.indexOf('.')
        var len    = strfi.substr(dotPos+1).length
        var times  = Math.pow(10, len)
        var intNum = parseInt(Math.abs(floatNum) * times + 0.5, 10)
        ret.times  = times
        if (isNegative) {
            intNum = -intNum
        }
        ret.num = intNum
        return ret
    }

    /*
     * 核心方法,实现加减乘除运算,确保不丢失精度
     * 思路:把小数放大为整数(乘),进行算术运算,再缩小为小数(除)
     *
     * @param a {number} 运算数1
     * @param b {number} 运算数2
     * @param digits {number} 精度,保留的小数点数,比如 2, 即保留为两位小数
     * @param op {string} 运算类型,有加减乘除(add/subtract/multiply/divide)
     *
     */
    function operation(a, b, digits, op) {
        var o1 = toInteger(a)
        var o2 = toInteger(b)
        var n1 = o1.num
        var n2 = o2.num
        var t1 = o1.times
        var t2 = o2.times
        var max = t1 > t2 ? t1 : t2
        var result = null
        switch (op) {
            case 'add':
                if (t1 === t2) { // 两个小数位数相同
                    result = n1 + n2
                } else if (t1 > t2) { // o1 小数位 大于 o2
                    result = n1 + n2 * (t1 / t2)
                } else { // o1 小数位 小于 o2
                    result = n1 * (t2 / t1) + n2
                }
                return digits ? (result / max).toFixed(digits) * 1 : Math.round(result / max)
            case 'subtract':
                if (t1 === t2) {
                    result = n1 - n2
                } else if (t1 > t2) {
                    result = n1 - n2 * (t1 / t2)
                } else {
                    result = n1 * (t2 / t1) - n2
                }
                return digits ? (result / max).toFixed(digits) * 1 : Math.round(result / max)
            case 'multiply':
                result = (n1 * n2) / (t1 * t2)
                return digits ? result.toFixed(digits) * 1 : Math.round(result)
            case 'divide':
                result = (n1 / n2) * (t2 / t1)
                return digits ? result.toFixed(digits) * 1 : Math.round(result)
        }
    }

    // 加
    function add(a, b, digits) {
        return operation(a, b, digits, 'add')
    }
    // 减
    function subtract(a, b, digits) {
        return operation(a, b, digits, 'subtract')
    }
    // 乘
    function multiply(a, b, digits) {
        return operation(a, b, digits, 'multiply')
    }
    // 除
    function divide(a, b, digits) {
        return operation(a, b, digits, 'divide')
    }

    return {
        add: add,
        subtract: subtract,
        multiply: multiply,
        divide: divide
    }
}();