传递和返回函数参数

Function Arguments Passing and Return

本文关键字:函数 参数 返回      更新时间:2023-09-26
  var foo = {
    bar: function() { return this.baz; },
    baz: 1
  };
  (function(){
    return typeof arguments[0]();
  })(foo.bar);

为什么这个代码返回undefined ?

我假设arguments[0]包含foo.bar,这是一个函数。当通过arguments[0]()调用时,它应该返回函数求值的结果,在本例中为1。因此,typeof arguments[0]()应该返回"Number"(与typeof 1一样)。相反,它返回undefined。为什么?

要理解为什么this不是对函数所在对象的引用,您必须理解JavaScript没有类。它有功能

在JavaScript中,函数从来没有像在Java、c#等类语言中那样严格地"绑定"到对象。javascript函数只是另一种类型,就像stringnumber一样,这意味着您可以像其他类型一样在变量中传递函数。在您的示例中,foo.bar中包含的函数根本不知道foo。它只是一个函数,只关心它自己的事情。

那么this关键字是做什么的呢?它指向执行上下文。在您的示例中,您从全局作用域(即window)调用foo.bar内部的函数,因此这就是它所指向的。您可以使用apply()在正确的范围内调用函数,但为此您需要访问该范围(在本例中是foo对象)。这就否定了只传递函数而不传递对象的任何安全优势。

为了"修复"这个"问题",ECMAScript 5 (JavaScript的未来版本)引入了 bind() 。这个方便的函数允许您在将函数传递给另一个函数之前将其绑定到特定的执行范围,如下所示:
var foo = {
    bar: function() { return this.baz; },
    baz: 1
};
var callback = foo.bar.bind(foo);
(function(){
    return typeof arguments[0]();
}(callback));

代码将无法工作,因为在匿名函数中,当在另一个上下文中使用时,您将失去对foo对象的this.baz的引用

您可以使用apply()方法来重新定义上下文,如下所示

var foo = {
   bar: function() { return this.baz; },
   baz: 1
};
(function(){
   return arguments[0].apply(foo);
})(foo.bar);

,这将正确返回1,因为apply()方法将执行上下文更改为作为参数传递的对象

typeof arguments[0].apply(foo);

返回number

可以通过this语句引用foo

你应该写一个像下面这样的包装器,这将非常有用,如果我们想改变foo的名字,当我们有很多函数在foo

var foo = {
    bar: function() { return this.baz; },
    baz: 1
  };
(function(a){
 for( var i in a){ 
    if( typeof a[i] === "function" ){
      a[i] = (function(f){  
            return function(){
                return f.apply(a,arguments);
            }
      })(a[i])
    }
 }
})(foo);
  (function(){
    return typeof arguments[0]();
  })(foo.bar);

这是指bar函数本身。

var foo = {
    bar: function() {return foo.baz; },
    baz:1
  };
  (function(){
    return typeof arguments[0]();
  })(foo.bar);

小提琴:http://jsfiddle.net/W9Jqb/