高级函数

作用域安全的构造函数

当使用构造函数时,如果没有使用new来调用,可能会导致this映射到全局对象window上,导致错误对象属性的意外增加。

而作用域安全的构造函数在进行任何更改千,首先确认this对象是否是正确类型的对象。如果不是,会创建新的实例并返回

1
2
3
4
5
6
7
8
9
function Person(name,age,job){
if(this instanceof Person){
this.name = name;
this.age = age;
this.job = job;
}else{
return new Person(name,age,job);
}
}

不过需要注意的是,这个模式锁定了可以调用构造函数的环境。如果使用构造函数窃取模式的继承且不适用原型链,那么这个继承很可能被破坏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function Polygon(sides){
if(this instanceof Polygon){
this.sides = sides;
this.getArea = function(){
return 0;
}
}else{
return new Polygon(sides);
}
}
function Rectangle(width,height){
Polygon.call(this,2);
this.width = width;
this.height = height;
this.getArea = function(){
return this.width*this.height;
}
}
Rectangle.prototype = new Polygon();
var rect = new Rectangle(5,10);
alert(rect.sides) //2

惰性载入函数

惰性载入表示该函数执行的分支仅会发生一次:即函数第一次调用的时候。在第一次调用的过程中,该函数会被覆盖为另外一个按合适方式执行的函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var key = 0; 
function createVar(){
console.log('hello');
if(key == 1){
createVar = function(){
return 111;
}
}else if( key ==2 ){
createVar = function(){
return 222;
}
}else{
createVar = function(){
return 333;
}
}
return createVar();
}

console.log(createVar());
console.log(createVar());
console.log(createVar());
console.log(createVar());
//输出
hello
333
333
333
333

两个主要优点:

  • 要执行的适当代码只有当实际调用函数时才进行
  • 尽管第一次调用该函数会因为额外的第二个函数调用而稍微慢一点,后续调用会更快

函数绑定

函数绑定要创建一个函数,可以在特定环境中以指定参数调用另一个函数。常常和回调函数与事件处理程序一起使用,以便在将函数作为变量传递时保留代码执行环境

使用闭包可能使代码变得难以理解和调试,可以使用bind函数

1
2
3
4
5
function bind(fn,context){
return function(){
return fn.apply(context,arguments);
}
}

在bind中创建了一个闭包,闭包使用apply调用传入的函数,并传递context对象和参数

缺点:被绑定函数与普通函数相比有更多的开销——需要更多的内存,同时也因为多重调用稍微慢一点,最好只在必要时使用

函数柯里化

用于创建已经设置好了一个或多个参数的函数。基本方法和函数绑定是一样的:使用闭包返回一个函数。

两者的区别在于:当函数被调用时,返回的函数还需要设置一些传入的参数

1
2
3
4
5
6
7
8
function add(num1,num2){
return num1+num2;
}
function curriedAdd(num2){
return add(5,num2);
}
alert(add(2,3)); //5
alert(curriedAdd(3)) //8
1
2
3
4
5
6
7
8
9
//创建柯里化函数的通用方式
function curry(fn){
let 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);
}
}
1
2
3
4
5
function add(num1,num2){
return num1+num2;
}
var curriedAdd = curry(add,5);
alert(curriedAdd(3)); //8

JS中的柯里化函数和绑定函数提供了强大的动态函数创建功能,使用curry还是bind要根据是否需要object对象响应来决定。

它们都能用于创建复杂的算法和功能,当然两者都不应滥用,因为每个函数都会带来额外的开销


高级函数
https://blog-theta-ten.vercel.app/2021/09/21/高级函数/
作者
Chen
发布于
2021年9月21日
许可协议