abbshr / abbshr.github.io

人们往往接受流行,不是因为想要与众不同,而是因为害怕与众不同

Home Page:http://digitalpie.cf

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

盘点ES5核心内容——函数篇

abbshr opened this issue · comments

对于函数来说,ES5并没有多大改动,主要是因为JavaScript里的函数本身就足够强大。不过这里增加了一些简单却又十分实用的内容。

arguments实参对象

arguments标示符作为函数的实参列表,在ES5版本下有了改动。

arguments[i]往往和实参互为别名,修改了二者中任意一个都会影响到另一个。而ES5移除了这一特性。

并且如果使用了"use stricts"语句(严格模式),arguments会变成保留字,也就是说不能将arguments当做变量名使用,不能给其赋值。

bind

bind方法是一个我认为最棒的新特性之一,因为它大大增强了函数的功能。其用法很简单:

var newfunc = func.bind(obj, arg1, arg2, ...);

意思是将函数func作为obj对象的方法(func的this绑定至obj),并传入预设参数arg1,arg2...,最后返回一个经过配置后的新函数newfunc

这在函数式编程领域里被称作“Currying”(“柯里化”),也叫“惰性求值”或“部分求值”,是一种应用极广的概念。

该方法的用处很大,在实际应用中我们可用它来做函数的“预配置”、优化层层嵌套的代码结构:

function foo(s) {
    var c, a;
    // 这里使用了bind方法,
    // 将c和a预填充到handler函数的前两个参数中
    s.on('event', handler.bind(s, c, a));
}

function handler(c, a, err, arg) {
    // handle arguments
    arg.on('e', cb.bind(null, c, a, err, arg));
}

function cb(c, a, err, arg, arg1) {
    // ...
}

如果不用绑定,代码就会变成这种模样:

function foo(s) {
    var c, a;
    s.on('event', function handler( err, arg) {
        // handle c, a, err, arg
        arg.on('e', function (arg1) {
            // handle arg1, err, arg
        });
    });
}

这里看起来还算好,不过一旦嵌套和函数数量一多,代码结构就变混乱了

定义嵌套函数的原因往往是因为要使用外部作用域的变量,bind方法的这种技术允许函数不必嵌套定义,在闭包上调用bind,绑定需要的参数即可。

当然,bind并非ES5的专利。在ES3中就可以通过函数的apply方法和返回闭包来模拟这种技术。

不过经过bind返回的函数与模拟出来的bind返回值有本质上的不同:bind方法返回的函数,形参长度是原长度 - 预填充实参个数,就像预填充的参数原本不存在一样。除此之外,返回的这个函数并** 不像其它函数一样包含prototype属性 **,但如果将其作为构造函数调用,则实例化的对象将使用原始函数的prototype属性作为自己的原型__proto__