函数调用
函数只是对象的一种类型。
所有Function对象都有呼叫和应用执行调用它们的Function对象的方法。
调用时,这些方法的第一个参数指定将由这
函数执行期间的关键字-如果无效的
或未定义
,全局对象,窗口
,用于这
.
因此,调用函数。。。
其中AmI=“窗口”;函数foo(){return“this is”+this.whereAmI+“with”+arguments.length+“+argument”;}
…带括号-foo()
-等于foo.call(未定义)
或foo.apply(未定义)
,这是有效地一样foo.call(窗口)
或foo.apply(窗口)
.
>>>foo()“这是一个有0个参数的窗口”>>>foo.call()“这是包含0个参数的窗口”
的其他参数呼叫
作为参数传递给函数调用,而单个附加参数传递给应用
可以将函数调用的参数指定为类数组对象。
因此,foo(1、2、3)
等于foo.call(空,1,2,3)
或foo.apply(空,[1,2,3])
.
>>>foo(1,2,3)“这是带有3个参数的窗口”>>>foo.apply(空,[1,2,3])“这是带有3个参数的窗口”
如果函数是对象的属性。。。
var对象={其中AmI:“obj”,foo:foo};
…通过对象访问对函数的引用并用括号调用它-对象.foo()
-等于foo.call(对象)
或foo.apply(对象)
.
然而,作为对象属性持有的函数并没有“绑定”到这些对象。正如您在定义中所看到的对象
如上所述,因为函数只是对象的一种类型,所以可以引用它们(因此可以通过引用传递给函数调用或通过引用从函数调用返回)。传递对函数的引用时,没有关于传递位置的附加信息从因此,会发生以下情况:
>>>baz=obj.foo;>>>baz();“这是包含0个参数的窗口”
调用我们的函数引用,巴兹
,不为调用提供任何上下文,因此它实际上与baz.call(未定义)
,所以这
最终引用窗口
.如果我们愿意巴兹
知道它属于对象
,我们需要在以下情况下以某种方式提供该信息巴兹
调用,这是呼叫
或应用
和闭包开始发挥作用。
范围链
函数绑定(func,context){返回函数(){函数应用(上下文、参数);};}
当一个函数被执行时,它会创建一个新的作用域并引用任何封闭作用域。在上例中创建匿名函数时,它引用了创建它的范围,即绑定
的范围。这被称为“关闭”
[全局范围(窗口)]-其中AmI、foo、obj、baz|[绑定范围]-func,上下文|[匿名范围]
当您尝试访问变量时,会遍历此“范围链”以查找具有给定名称的变量-如果当前范围不包含该变量,则查看链中的下一个范围,依此类推,直到到达全局范围。当返回匿名函数并绑定
执行完成后,匿名函数仍然引用绑定
的范围,所以绑定
的范围不会“消失”。
鉴于以上所述,您现在应该能够理解以下示例中的范围是如何工作的,以及为什么要在具有特定值的“预绑定”周围传递函数的技术这
当它被称为works时:
>>>baz=绑定(obj.foo,obj);>>>baz(1,2);“这是带有2个参数的obj”