函数调用
在JavaScript 中,函数和其他东西一样都是对象。然而,和其他对象不同的是,函数是可调用的。函数内上下文,如this 的取值,取决于调用它的位置和方法。
除了使用方括号调用函数之外,还有其他两种方法可以调用函数:apply() 和call()。两者的区别在于传入函数的参数的形式。
apply() 函数有两个参数:第1 个参数是上下文,第2 个参数是参数组成的数组。如果上下文是null,则使用全局对象代替。例如:
- function.apply(this, [1, 2, 3])
广州网站建设,广州网站设计,广州网站制作,网站建设,网站设计,广州网站建设公司,广州网站设计公司
call() 函数的行为和apply() 函数的并无不同,只是使用方法不一样。call() 的第1 个参数是上下文,后续是实际传入的参数序列。换句话说,这里使用多参数——而不是类似apply() 的数组——来将参数传入函数。- function.call(this, 1, 2, 3);
为什么要更换上下文?这的确是一个问题,因为其他编程语言不允许手动更换上下文也没什么不好。JavaScript 中允许更换上下文是为了共享状态,尤其是在事件回调中。(依个人所见,这是语言设计中的一个错误,因为这会对初学者造成一些困扰,并引入一些bug。但亡羊补牢为时已晚,你需要花精力来弄清楚它们是如何工作的。)
jQuery 在其API 的实现中就利用了apply() 和call() 来更改上下文,比如在事件处理程序中或者使用each() 来做迭代时。起初这很让人费解,一旦你理解了就会发现它非常有用:
- $('.clicky').click(function(){
- // ‘this’指向当前节点
- $(this).hide();
- });
- $('p').each(function(){
- // ‘this’指向本次迭代
- $(this).remove();
- });
广州网站建设,广州网站设计,广州网站制作,网站建设,网站设计,广州网站建设公司,广州网站设计公司
为了访问原始上下文,可以将this 的值存入一个局部变量中,这是一种常见的模式,比如:- var clicky = {
- wasClicked: function(){
- /* ... */
- },
- addListeners: function(){
- var self = this;
- $('.clicky').click(function(){
- self.wasClicked()
- });
- }
- };
- clicky.addListeners();
然而,我们可以使用apply来将这段代码变得更干净一些,通过将回调包装在另外一个匿名函数中,来保持原始的上下文:
- var proxy = function(func, thisObject){
- return(function(){
- return func.apply(thisObject, arguments);
- });
- };
- var clicky = {
- wasClicked: function(){
- /* ... */
- },
- addListeners: function(){
- var self = this;
- $('.clicky').click(proxy(this.wasClicked, this));
- }
- };
因此在上面的例子中,我们在点击事件的回调中指定了要使用的上下文;jQuery 中调用这个函数所用的上下文就可以忽略了。实际上,jQuery 也包含了实现这个功能的API,
你或许已经猜到了,就是jQuery.proxy() :
- $('.clicky').click($.proxy(function(){ /* ... */ }, this));
使用apply() 和call() 还有其他很有用的原因,比如“委托”。我们可以将一个调用委托给另一个调用,甚至可以修改传入的参数:
- var App {
- log: function(){
- if (typeof console == "undefined") return;
- // 将参数转换为合适的数组
- var args = jQuery.makeArray(arguments);
- // 插入一个新的参数
- args.unshift("(App)");
- // 委托给console
- console.log.apply(console, args);
- }
- };
在这个例子中首先构建了一个参数数组,然后将我们自己的参数添加进去,最后将这个调用委托给了console.log()。你可能对arguments 变量不熟悉,它是当前调用的作用域内解释器内置的用来保存参数的数组。但它并不是真正的数组,比如它是不可变的,因此我们需要通过jquery.makeArray() 将其转换为可用的数组。