函数那些事

# 函数那些事

[TOC]

函数声明:

function sum(a,b){
    return a+b;
}
1
2
3

函数表达式:

var sum = function(a,b){
    return a+b;
};
1
2
3

Function构造函数:

// 不推荐使用,影响函数解析性能
var sum = new Function('a','b','return a+b');
1
2

# 一、 函数柯里化

函数柯里化的基本方法和函数绑定是一样的:使用一个闭包返回一个函数。两者的区别在于,当函数被调用时,返回的函数还需要设置一些传入的函数。

# 1.1 实现

# 1.1.1 通用实现

function curry(fn, ...rest1) {
    return (...rest2) => {
        // 注意这个函数并没有考虑到执行环境,所以调用apply()时第一个参数是null。
        // return fn.apply(null, rest1.concat(rest2));
        return fn(...rest1,...rest2)
    };
}
1
2
3
4
5
6
7

# 1.2 作用

# 1.2.1 参数复用

# 1.2.2 提前返回

# 1.2.3 延迟计算/运行

# 二、函数参数

# 2.1 函数参数无法确定

用 arguments,一个对应于传递给函数的参数的类数组对象。它类似于Array,但除了length属性和索引元素之外没有任何Array属性。例如,它没有pop方法。但是它可以被转换为一个真正的Array

var args = Array.from(arguments);//Array.from() 方法从一个类似数组或可迭代对象中创建一个新的数组实例。
var args = [...arguments];
1
2

举例:遍历参数求和

function add() {
    var sum =0,
        len = arguments.length;
    for(var i=0; i<len; i++){
        sum += arguments[i];
    }
    return sum;
}
add()                           // 0
add(1)                          // 1
add(1,2,3,4);                   // 10
1
2
3
4
5
6
7
8
9
10
11

arguments对象可以与剩余参数、默认参数和解构赋值参数结合使用。

function foo(...args) {
    return args;
}
foo(1, 2, 3);  // [1,2,3]
1
2
3
4

# 2.2 强制参数

默认情况下,如果不向函数参数传值,那么JS会将函数参数设置为undefined,而不会抛出警告或错误。

mandatory = () => {
    throw new Error('Missing parameter!');
}
foo = (bar = mandatory()) => { return bar};
foo();	// Uncaught Error: Missing parameter!
foo(1);	// 1
1
2
3
4
5
6

# 三、性能优化

# 3.1惰性载入函数

出处:https://juejin.im/post/5b51e5d3f265da0f4861143c#heading-12 (opens new window)

在某个场景下我们的函数中有判断语句,这个判断依据在整个项目运行期间一般不会变化,所以判断分支在整个项目运行期间只会运行某个特定分支,那么就可以考虑惰性载入函数

function foo(){
    if(a !== b){
        console.log('aaa')
    }else{
        console.log('bbb')
    }
}

// 优化后
function foo(){
    if(a != b){
        foo = function(){
            console.log('aaa')
        }
    }else{
        foo = function(){
            console.log('bbb')
        }
    }
    return foo();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

那么第一次运行之后就会覆写这个方法,下一次再运行的时候就不会执行判断了。当然现在只有一个判断,如果判断很多,分支比较复杂,那么节约的资源还是可观的。

# 3.2 一次性函数

跟上面的惰性载入函数同理,可以在函数体里覆写当前函数,那么可以创建一个一次性的函数,重新赋值之前的代码相当于只运行了一次,适用于运行一些只需要执行一次的初始化代码。

var sca = function() {
    console.log('msg')
    sca = function() {
        console.log('foo')
    }
}
sca()        // msg
sca()        // foo
sca()        // foo
1
2
3
4
5
6
7
8
9