function hello() {
alert('hello');
}
function hi() {
return function() {
alert('hi');
}
}
我知道通过执行 hi()();
我可以运行第二个函数,但我很少在代码中看到这样的写法。那么如何在不使用此方法的情况下返回函数呢?因为我经常看到人们这样做。
function hello() {
alert('hello');
}
function hi() {
return function() {
alert('hi');
}
}
我知道通过执行 hi()();
我可以运行第二个函数,但我很少在代码中看到这样的写法。那么如何在不使用此方法的情况下返回函数呢?因为我经常看到人们这样做。
返回函数可以从第一次调用的函数中缓存一些变量,然后您可以稍后在返回函数上执行某些操作。
例如,
function hi(lastName) {
return function(firstName) {
alert('hi ' + firstName + lastName);
}
}
var chen = hi("Chen");
chen("Jumper");
chen("Dennis");
number
, string
, boolean
, object
, undefined
- 和 - function
。
(还有一些伪类型-如Infinity
和NaN
,但现在不管它,稍后再谷歌它。)undefined
,但这也是一个返回值。 但是,说每个表达式都有一个返回值- 这包括函数定义。两者之间没有太大区别:function foo(){}
并且
foo = function(){}
()
运算符稍后执行它。是的-运算符。()
是一个运算符,它执行引用后面的代码,并向其提供参数堆栈,其中包含()
中提供的值。foo
函数并将其保留在变量foo
中之后,您可以随时调用foo()
- 这是因为foo
是一个变量,它保存对函数的引用,稍后可以执行-只要变量foo
没有被覆盖另一个值或被同名的更局部变量隐藏即可。foo()
首先评估foo
的含义,然后将其作为带有空参数堆栈的函数操作(因为它是foo()
,而不仅仅是foo
)。
在这种意义上,您可以评估foo()
的含义,然后将其作为函数进行操作-就像在您的原始示例foo()()
中一样。你知道吗?您可以继续进行此操作:foo()()()
和foo()()()
,但是请注意,一旦您尝试对要操作的评估表达式()
不是函数引用,您将获得异常。 obj[ handler ](42);
obj[ getHandlerName(handler) ] (42);
(为了简短,我只解释第一个) - 它首先评估obj
是什么,然后假设它是一个对象并评估obj[handler]
,然后假设它是一个函数并尝试将其执行为obj [handler](42)
- 将42作为单个参数传递。请注意,handler是一个变量名,可以包含任何值,在这种情况下,它将作为字符串尝试(或使用它的toString()方法的返回值 - 因为[]也是一个运算符,但那是另一篇文章的主题)。
这个参数堆栈是由函数的执行隐含的,并且没有关于提供给函数和函数实际期望的参数数量或类型的限制。
在执行期间传递给函数的所有参数都可以使用隐含参数arguments
访问,它是一个伪数组构造 - 最好简单地描述为参数堆栈...为什么是伪数组?它不响应Array提供的任何API,除了属性length
和索引器访问(即arguments [0],arguments [1]等)。
函数可以为它希望处理的参数定义变量名,这些变量名将对应于参数变量名中的0索引位置arguments [n]
。
现在,如果一个函数是一种数据类型,它可以返回并稍后执行。在那种情况下,没有太大的区别
function a(){
return function b(){}
}
并且
function a(){
function b(){}
return b; //pay attention - no braces = don't execute b, return the func-ref.
}
and
function a(){
var b = function(){}
return b;
}
实际上,最后一个问题被认为是不规范的,下一个问题将帮助您了解原因。
第二个问题 - 作用域和闭包。
在JavaScript中,变量的作用域是定义它们的函数。(对于来自其他语言的程序员来说,这很令人困惑,因为在其他语言中,变量仅限于它们被定义的块 - 这种限制不适用于JavaScript。只有函数体才具有作用域的目的)。
从这个意义上讲,最顶层,也就是“根”或“主” - 是最高级别,在那里定义全局变量。这意味着在根上定义的变量和函数可供执行的所有代码访问,并且因此充当全局变量。
闭包是指执行函数在其中定义其他函数,并“公开”其中一个或多个函数 - 通过将它们分配给全局变量,或通过返回一个函数引用,稍后由调用定义函数的代码保留。
现在,由于如上所述 - 每次执行函数都会定义至少一个名为arguments
的变量 - 除了它定义的参数变量名称之外,它还可以访问任何定义在其中的函数的任何代码 - 或由定义在其中的函数的执行定义的代码(或由执行它的函数定义的函数的执行定义的代码,或由执行...好吧,你懂了)。
这意味着:
var G = "global"
function a(x,y){
var h = "local to closure a"
, z = function(){
var k = "local to this function"
//code here can access G
//code here can access k
// - and x and y - and - h and z!
}
;
return z;
}
这就为一些非常有趣的用法打开了空间 - 比如回调函数可以访问本地变量,这些变量保存了由参数传递给while检索回调z时定义的私有状态。
我希望这样能够更简单地将一些东西放在一起 :)
自执行函数和回调函数都是常见的方法。
在这里找到可用的示例: http://jsfiddle.net/ezmilhouse/9BbGC/
// self executing
function hi( text ) {
return (function(text) {
alert(text);
})(text);
}
hi('ho');
// callback
function ho(callback){
callback();
}
ho(function(){
alert('ha');
});
hi()
函数运行良好,它返回一个完全按照设计的函数。你可以像你展示的那样直接使用hi()()
执行返回的函数,或者像处理从任何函数返回的值一样处理返回的函数。那么,你的问题到底是什么? - Davidhi()()
能够实现它的功能。hi()
返回一个函数。hi()()
返回并随后执行一个函数。你可以对返回的函数做任何想做的事情,包括执行它。如果你只想返回它而不立即执行它,那么只需调用hi()
并将返回值分配给一个变量即可。 - David