What is a closure
-
Closure refers to a function that has access to variables in the scope of another function.
The most common way to create a closure is to create another function within a function and access the local variables of this function through another function.function fn1(){ var a=1; // 因为返回的函数被存储在全局变量中, // 并且这个返回的函数使用这个a的局部变量,因此a被保存在堆中 //闭包会产生内存泄漏 return function(){ a++; console.log(a); } } var f=fn1(); f() f();
Features and advantages of closures
Characteristics of closures
- Function nested function
- The function can reference external parameters and variables
- Parameters and variables will not be recycled by the garbage collection mechanism
Advantages of closures
- Avoid pollution of global variables
- In order to get private variables
- Hope that a variable resides in memory for a long time
Disadvantages of closures
- Will cause a memory leak
var Utils=(function(){
var num=0;
return {
a:function(){
num++;
console.log(num);
},
b:function(){
}
}
})();
Utils.a();
Utils.a();
Utils.a();
Currying
What is currying
-
It refers to the method of converting a multi-parameter function into a single-parameter function
-
Collect parameters for storage, and execute the actual function to be processed when there are no parameters
function curry(fn){
var arr=[];
return function(){
if(arguments.length>0){//有参数传入
arr=arr.concat(Array.from(arguments));//将arguement转化为数组放进去
return arguments.callee;//自身函数
}else{//没有传参
return fn.apply(null,arr);
}
}
}
function fns(){//解决实际融合问题
return Array.from(arguments).reduce((value,item)=>value+=item);//求和
}
var s=fns(1,2,3,4,5,6)
console.log(s);
var sum=curry(fns);
var s=sum(1)(2,3)(4,5,6)()
console.log(s);
Currying advantages
- 1. Parameter reuse
// 正常正则验证字符串 reg.test(txt)
// 函数封装后
function check(reg, txt) {
return reg.test(txt)
}
check(/\d+/g, 'test') //false
check(/[a-z]+/g, 'test') //true
// Currying后
function curryingCheck(reg) {
return function(txt) {
return reg.test(txt)
}
}
var hasNumber = curryingCheck(/\d+/g)
var hasLetter = curryingCheck(/[a-z]+/g)
hasNumber('test1') // true
hasNumber('testtest') // false
hasLetter('21212') // false
- 2. Confirm in advance
- 3. Delayed operation
Function.prototype.bind = function (context) {
var _this = this
var args = Array.prototype.slice.call(arguments, 1)
return function() {
return _this.apply(context, args)
}
}//bind是柯里化
Packaging method
// 初步封装
var currying = function(fn) {
// args 获取第一个方法内的全部参数
var args = Array.prototype.slice.call(arguments, 1)
return function() {
// 将后面方法里的全部参数和args进行合并
var newArgs = args.concat(Array.prototype.slice.call(arguments))
// 把合并后的参数通过apply作为fn的参数并执行
return fn.apply(this, newArgs)
}
}
// 支持多参数传递
function progressCurrying(fn, args) {
var _this = this
var len = fn.length;
var args = args || [];
return function() {
var _args = Array.prototype.slice.call(arguments);
Array.prototype.push.apply(args, _args);
// 如果参数个数小于最初的fn.length,则递归调用,继续收集参数
if (_args.length < len) {
return progressCurrying.call(_this, fn, _args);
}
// 参数收集完毕,则执行fn
return fn.apply(this, _args);
}
}
Currying performance
- Accessing the arguments object is usually slower than accessing named parameters
- Some older browsers are quite slow in implementing arguments.length
- Using fn.apply(…) and fn.call(…) is usually slightly slower than calling fn(…) directly
- Creating a large number of nested scopes and closure functions will bring costs, both in memory and speed
- In fact, in most applications, the main performance bottleneck is operating on DOM nodes. The performance loss of this js is basically negligible, so curry can be used directly and safely.
Anti-Currying
- The meaning and usage are just the opposite compared to function currying, which expands the scope of application and creates a function with a wider application range. Extend methods that were originally applicable only to specific objects to more objects