阅读 104

js部分

判断this

现在我们可以根据优先级来判断函数在某个调用位置应用的是哪条规则。可以按照下面的 顺序来进行判断:

  1. 函数是否在new中调用(new绑定)?如果是的话this绑定的是新创建的对象。 var bar = new foo()
  2. 函数是否通过call、apply(显式绑定)或者硬绑定调用?如果是的话,this绑定的是 指定的对象。 var bar = foo.call(obj2)
  3. 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this绑定的是那个上 下文对象。 var bar = obj1.foo()
  4. 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到undefined,否则绑定到 全局对象。 var bar = foo() 就是这样。对于正常的函数调用来说,理解了这些知识你就可以明白 this 的绑定原理了。 不过......凡事总有例外。

作用域闭包

定义: 当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。

原型

模板编译函数

    let tem = '我是{{obj.name}},我爱{{  obj.hobby?"singing":"dance"}}'
    let obj = {
        name: "gp",
        hobby: 0
    }

    compile(tem, obj) // 我是gp,我爱dance
    function compile(tem, obj){

        let reg = /\{\{(.*?)\}\}/g
        let strFun = '""'

        var strArr = tem.split(reg)
        var regArr = tem.match(reg)
        console.log(strArr) // ["我是", "obj.name", ",我爱", "obj.hobby?"singing":"dance"", ""]
        console.log(regArr) // ["{{obj.name}}", "{{obj.hobby?"singing":"dance"}}"]

        strArr.forEach((item, index)=>{
            if(item !== "" && regArr.toString().includes(item)){
                strFun += "+(" +  item +")"
            }else{
                strFun += "+"+ '"' + item +'"'
            }

        })
        console.log(strFun) // ""+"我是"+(obj.name)+",我爱"+(obj.hobby?"singing":"dance")+""
        var fun = new Function( 'return ' + strFun)
        return fun()
    }
复制代码

判断对象为空

# 自身没有可枚举的
function isObjectEmpty(obj) {
  if (obj) {
    for (var prop in obj) {
      if (obj.hasOwnProperty(prop)) {
        return false;
      }
    }
  }
  return true;
}
复制代码

判断类数组

   function isLength(value) {
      return typeof value == 'number' &&
        value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
    }
    
   function isArrayLike(value) {
      return value != null && isLength(value.length) && !isFunction(value);
    }
复制代码

柯里化

const curry = func =>{
	 const g = (...allArgs) => allArgs.length >= func.length ?
		 func(...allArgs) :
		 (...args)=> g(...allArgs, ...args)

	return g
}

const foo = curry( (a,b,c,d) => {
	console.log(a, b, c, d)
})
复制代码

全排列

	function permutate(str) {

		var result=[];
		if(str.length==1){
			return [str]
		}else{

			var preResult=permutate(str.slice(1));
			for (var j = 0; j < preResult.length; j++) {
				for (var k = 0; k < preResult[j].length+1; k++) {
					var temp=preResult[j].slice(0,k)+ str[0]+ preResult[j].slice(k);
					result.push(temp);
				}
			}
			return result;

		}
	}

	console.log(permutate("abc"));
复制代码

debounce

const debounce = (func, delay) => {
  let inDebounce
  return function() {
    const context = this
    const args = arguments
    clearTimeout(inDebounce)
    inDebounce = setTimeout(() => func.apply(context, args), delay)
  }
}
复制代码

throttle

const throttle = (func, limit) => {
  let lastFunc
  let lastRan
  return function() {
    const context = this
    const args = arguments
    if (!lastRan) {
      func.apply(context, args)
      lastRan = Date.now()
    } else {
      clearTimeout(lastFunc)
      lastFunc = setTimeout(function() {
        if ((Date.now() - lastRan) >= limit) {
          func.apply(context, args)
          lastRan = Date.now()
        }
      }, limit - (Date.now() - lastRan))
    }
  }
}
复制代码

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;
};
复制代码

四舍五入-原生toFixed() 方法不准确

function toFixed(num, s) {
  var times = Math.pow(10, s);
  var des = num * times + 0.5;
  des = parseInt(des, 10) / times;
  return des + '';
}
复制代码

小数相乘

function accMul(arg1, arg2) {
 let m = 0,
   s1 = arg1.toString(),
   s2 = arg2.toString()
 try {
   m += s1.split('.')[1].length
 } catch (e) {} // eslint-disable-line
 try {
   m += s2.split('.')[1].length
 } catch (e) {} // eslint-disable-line

 return Number(s1.replace('.', '')) * Number(s2.replace('.', '')) / Math.pow(10, m)
}
复制代码

使对象拥有 iterator

var myObject = { a: 2,
  b: 3 };
Object.defineProperty( myObject, Symbol.iterator, { enumerable: false,
  writable: false,
  configurable: true,
  value: function() { var o = this;
    var idx = 0;
    var ks = Object.keys( o ); return {
      next: function() { return {
        value: o[ks[idx++]],

        done: (idx > ks.length)
      };

      } };
  } } );
// 手动遍历 myObject
var it = myObject[Symbol.iterator]();
it.next(); // { value:2, done:false } 
it.next(); // { value:3, done:false }
it.next(); // { value:unde ned, done:true }
// 用 for..of 遍历 myObject 
for (var v of myObject) { console.log( v );
}
// 2 
// 3
复制代码

待续。。。