var foo = (function foo(){ if(a != b){ return function(){ console.log('aaa') } }else{ return function(){ console.log('bbb') } }})();
这里创建一个匿名,自执行的函数,用来确定应该使用哪一个函数来实现。
惰性函数的优点就是只在第一次执行分支时牺牲一点点性能
函数绑定
请使用fun.bind([, arg1[, arg2[, …]]])
当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。当使用new 操作符调用绑定函数时,该参数无效
arg1,arg2,…
当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法
返回
由指定的this值和初始化参数改造的原函数拷贝
一个例子
let person = { name: 'addone', click: function(e){ console.log(this.name) }}let btn = document.getElementById('btn');EventUtil.addHandle(btn, 'click', person.click);
这里创建了一个对象js 判断节点是否存在,然后将.click方法分配给DOM按钮的事件处理程序,当你点击按按钮时,会打印出,原因是执行时this指向了DOM按钮而不是
解决方案: 将this强行指向
EventUtil.addHandle(btn, 'click', person.click.bind(person));
函数柯里化
函数柯里化是把接受多个参数的函数转变成接受单一参数的函数
function add(num1, num2){ return num1 + num2;}function curryAdd(num2){ return add(1, num2);}add(2, 3) // 5curryAdd(2) // 3
这个例子用来方便理解柯里化的概念
下面是创建函数柯里化的通用方式
function curry(fn){ var args = Array.prototype.slice.call(arguments, 1); return function(){ let innerArgs = Array.prototype.slice.call(arguments); let finalArgs = args.concat(innerArgs); return fn.apply(null, finalArgs); }}
第一个参数是要进行柯里化的函数,其他参数是要传入的值。这里使用Array..slice.call(, 1)来获取第一个参数后的所有参数(外部)。在返回的函数中js 判断节点是否存在,同样调用Array..slice.call()让来存放所有的参数(内部),然后用将内部外部参数组合,用apply传递给函数
function add(num1, num2){ return num1 + num2;}let curryAdd1 = curry(add, 1);curryAdd1(2); // 3let curryAdd2 = curry(add, 1, 2);curryAdd2(); // 3
防篡改对象
中任何对象都可以被同一环境中运行的代码修改,所以开发人员有时候需要定义防篡改对象(-proof ) 来保护自己
不可扩展对象
默认情况下所有对象都是可以扩展的(添加属性和方法)
let person = { name: 'addone' };person.age = 20;
第二行为对象扩展了age属性,当然你可以阻止这一行为,使用.()
let person = { name: 'addone' };Object.preventExtensions(person);person.age = 20;person.age // undefined
你还可以用.()来判断对象是不是可扩展的
let person = { name: 'addone' };Object.isExtensible(person); // trueObject.preventExtensions(person);Object.isExtensible(person); // false
请记住这是不可扩展!!,即不能添加属性或方法
密封的对象
密封对象不可扩展,且不能删除属性和方法
let person = { name: 'addone' };Object.seal(person);person.age = 20;delete person.name;person.age // undefinedperson.name // addone
相对的也有.()来判断是否密封
let person = { name: 'addone' };Object.isExtensible(person); // trueObject.isSealed(person); // falseObject.seal(person);Object.isExtensible(person); // falseObject.isSealed(person); // true
冻结的对象
这是最严格的防篡改级别,冻结的对象即不可扩展,又密封,且不能修改
let person = { name: 'addone' };Object.freeze(person);person.age = 20;delete person.name;person.name = 'addtwo'person.age // undefinedperson.name // addone
同样也有.来检测
let person = { name: 'addone' };Object.isExtensible(person); // trueObject.isSealed(person); // falseObject.isFrozen(person); // falseObject.freeze(person);Object.isExtensible(person); // falseObject.isSealed(person); // trueObject.isFrozen(person); // true
以上三种方法在严格模式下进行错误操作均会导致抛出错误
高级定时器
阅读前提
大概理解的基本执行机制和js事件机制
重复的定时器
当你使用重复定义多个定时器的时候,可能会出现某个定时器代码在代码再次被添加到执行队列之前还没有完成执行,导致定时器代码连续执行多次。
机智引擎解决了这个问题,使用()的时候,仅当没有该定时器的其他代码实例时,才会将定时器代码添加到队列中。但这还会导致一些问题:
为了避免这个两个问题,你可以使用链式()调用
setTimeout(function(){ TODO(); setTimeout(arguments.callee, interval);}, interval)
.获取了当前执行函数的引用,然后为其设置另外一个定时器,这样就确保在下一次定时器代码执行前,必须等待指定的间隔。
浏览器对长时间运行的脚本进行了制约,如果代码运行超过特定的时间或者特定语句数量就不会继续执行。
如果你发现某个循环占用了大量的时间,那么对于下面这两个问题
如果你的两个答案都是”否”,那么你可以使用一种叫做数组分块(array ) 的技术。基本思路是为要处理的项目创建一个队列,然后使用定时器取出下一个要出处理的项目进行处理,然后再设置另一个定时器。
function chunk(array, process, context){ setTimeout(function(){ // 取出下一个项目进行处理 let item = array.shift(); process.call(item); if(array.length > 0){ setTimeout(arguments.callee, 100); } }, 100)}
这里接受三个参数,要处理的数组,处理的函数,运行该函数的环境(可选),这里设置间隔100ms是个效果不错的选择
如果你一个函数需要50ms以上时间完成,那么最好看看能否将任务分割成一系列可以使用定时器的小任务
函数节流()
节流的目的是防止某些操作执行的太快。比如在调整浏览器大小的时候会触发事件,如果在其内部进行一些DOM操作,这种高频率的更爱可能会使浏览器崩溃。为了避免这种情况,可以采取函数节流的方式。
function throttle(method, context){ clearTimeout(method.tId); method.tId = setTimeout(function(){ method.call(context); }, 100)}
这里接受两个参数,要执行的函数,执行的环境。执行时先清除之前的定时器,然后将当前定时器赋值给方法的tId,之后调用call来确定函数的执行环境。
一个应用的例子
function resizeDiv(){ let div = document.getElementById('div'); div.style.height = div.offsetWidth + "px";}window.onresize = function(){ throttle(resizeDiv);}
给个,转发谢谢
Java创建对象方式
深入理解Java内存模型
Java线上% 问题排查
Java加密与解密之对称加密DES
Java分布式事务实现
你不得不知道的七个小技巧
中使用Cache及的使用
jpa 实现读写分离
MVC 异步请求方式
本文到此结束,希望对大家有所帮助。
本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至81118366@qq.com举报,一经查实,本站将立刻删除。发布者:简知小编,转载请注明出处:https://www.jianzixun.com/78380.html