什么是在javascript函数中实时使用函数?

时间:2014-01-30 05:26:11

标签: javascript

作为JavaScript的新手,我在JavaScript中遇到了一个功能,我们可以在一个看起来很酷的函数中编写函数,但我不明白它的任何实际用途以及如何调用子函数?

var parent = "global";
function Parent() {
    alert(parent);

    function child() {
        alert("i am child");
    }
}

所以,在上面的例子中,函数parent嵌入了子函数,但我不确定以下两个问题:

  1. 这种语法/功能的实际用途是什么?

  2. 如何调用子功能?

3 个答案:

答案 0 :(得分:1)

我不确定是否有人真的给了你简单的答案。在child()函数中定义Parent()函数只是定义一个“局部”函数,其范围仅限于Parent()函数的代码中。它类似于仅存在于函数内的局部变量。

所以,当你有这个:

function Parent() {

    function child() {
        alert("i am child");
    }
}

您已经创建了一个名为child的新函数,可以从Parent()函数内部的代码中调用,如下所示:

function Parent() {

    function child() {
        alert("i am child");
    }

    child();
}

此函数在Parent()函数中是真正的本地函数,不能从其他任何地方调用。所以,这不起作用:

function Parent() {

    function child() {
        alert("i am child");
    }

}

child();   // this function will be undefined

以这种方式定义函数的最简单的原因只是包含它可以使用的位置并减少潜在的名称冲突。如果你不能像这样定义局部函数,那么所有函数都必须是全局的(或某些对象上的方法),并且你可能有一组可能的名称冲突。这样,您可以在它们应用的范围内定义函数,并且它们不会与在其自己的范围内以类似方式定义的任何其他函数发生冲突。


当您进入javascript的更高级用法时,child()函数也可以访问其父级的所有变量。所以,你可以这样做:

function Parent() {

    var msg = "Hello!";

    function child() {
        alert(msg);
    }

    child();   // will put up an alert that says "Hello!"
}

这允许那些本地函数从父上下文共享所有变量,而不必将它们全部传递给函数。这在使用回调时特别有用,因为它允许回调访问整个上下文,即使回调是由其他一些代码调用的。这是一个回调可以访问某些有用状态的简单示例。

function blink(elem, numTimes, duration) {
    var timer, visible = true;

    // callback function that is called
    function handleInterval() {
        // toggle visible state
        var val = visible ? "hidden" : "visible";
        elem.style.visibility = val;
        visible = !visible;
        --numTimes;
        if (numTimes <= 0) {
            clearInterval(timer);
        }
    }

    timer = setInterval(handleInterval, duration);
}

这里您注意到handleInterval()函数不仅可以访问blink()函数中的局部变量,还可以访问传递给它的参数。这允许我们在不使用全局变量的情况下保持setInterval()的某些状态。这里还有一个更高级的东西叫做闭包。关闭可能有点复杂的概念,但理解一些用途通常相当简单。

在这种情况下,调用blink()函数。它的工作是创建一个间隔计时器,当被调用时将切换传入元素的可见性状态。在一定数量的闪烁之后,它将停止间隔计时器。但是,所有blink函数都会调用setInterval()函数来调度间隔计时器。然后它立即完成并完成执行。但是,因为setInterval()函数已经被调度并且已经传递了对handleInterval()函数的引用,并且该函数在blink()函数的范围内,那么所有局部变量都是即使blink()函数已经完成执行,blink()函数仍然“保持活动”并运行。实际上,这些变量将一直保持活动状态,直到计时器停止,任何东西都不能再调用handleInterval()。如果javascript没有此功能,则此简单解决方案中的许多变量必须声明为全局变量或某个对象的属性,这些对象在此活动持续时间内持续存在。这种技术使代码更加清晰和自包含。


不必命名本地函数。他们也可以是匿名的。实现blink()的更典型的方法是使用内联匿名函数回调而不是给它起一个名字:

function blink(elem, numTimes, duration) {
    var timer, visible = true;

    timer = setInterval(function() {
        // toggle visible state
        var val = visible ? "hidden" : "visible";
        elem.style.visibility = val;
        visible = !visible;
        --numTimes;
        if (numTimes <= 0) {
            clearInterval(timer);
        }
    }, duration);
}

如果您只在一个地方调用此函数,那么它实际上不需要单独声明并给出一个名称。它可以像内容一样定义为匿名函数。

答案 1 :(得分:0)

这个概念主要用于OOJS(面向对象的JavaScript)。请考虑以下示例:

var Employee=function(ename,eage){
var _name=ename;
var _age=eage;
this.getName=function(){return _name;};
this.getAge=function(){return _age;};
};

var e1=new Employee("Xyz",45);
var e2=new Employee("Abc",23);
e1.getName(); //output=Xyz
e1.getAge(); // output=45
and so on ...

答案 2 :(得分:0)

这是一个闭包,它是一种控制JavaScript范围的方法。闭合件内部定义的任何东西都不会在闭合件外面看到。通过对您的功能进行少量修改,您可以这样调用它:

var parent = "global";
        function Parent(a) {
        alert(parent);

        function child(b) {
            alert(a + b); //child can see both a and b
        }

        return child;
    }

    parent(1)(2);

这可以用来实现currying,这里解释Javascript curry - what are the practical applications?