在JavaScript中,嵌套函数非常有用:闭包,私有方法以及你有什么......

什么是嵌套的PHP函数?有没有人使用它们,为什么?

这是我做过的一项小调查

<?php
function outer( $msg ) {
    function inner( $msg ) {
        echo 'inner: '.$msg.' ';
    }
    echo 'outer: '.$msg.' ';
    inner( $msg );
}

inner( 'test1' );  // Fatal error:  Call to undefined function inner()
outer( 'test2' );  // outer: test2 inner: test2
inner( 'test3' );  // inner: test3
outer( 'test4' );  // Fatal error:  Cannot redeclare inner()
有帮助吗?

解决方案

基本上没有,我一直认为这是解析器的副作用。

Eran Galperin错误地认为这些函数在某种程度上是私有的,在运行 outer()之前,它们只是未声明。它们也不是私人范围的,它们确实在全球范围内进行了调查,尽管延迟了。作为回调,外部回调仍然只能被调用一次。我仍然没有看到如何将它应用于一个很可能多次调用别名的数组。

我可以挖掘的唯一'真实世界'示例是只能运行一次,可以重写为IMO清洁。

我能想到的唯一用途是模块调用[name] _include方法,该方法在全局空间中设置几个嵌套方法并结合

if (!function_exists ('somefunc')) {
  function somefunc() { }
}

检查。

PHP的OOP显然是更好的选择:)

其他提示

如果您使用的是PHP 5.3,则可以使用匿名函数获得更多类似Javascript的行为:

<?php
function outer() {
    $inner=function() {
        echo "test\n";
    };

    $inner();
}

outer();
outer();

inner(); //PHP Fatal error:  Call to undefined function inner()
$inner(); //PHP Fatal error:  Function name must be a string
?>

输出:

test
test

[根据@PierredeLESPINAY的评论重写。]

它不仅仅是副作用,而且实际上是动态修改程序逻辑的一个非常有用的功能。它来自程序化的PHP时代,但如果您想以最直接的方式为某些独立功能提供替代实现,那么它也可以与OO架构派上用场。 (虽然OO在大多数情况下是更好的选择,但它是一种选择,而不是授权,而一些简单的任务不需要额外的任务。)

例如,如果您动态/有条件地从框架加载插件,并希望使插件作者的生活变得非常简单,那么您可以为插件未覆盖的一些关键功能提供默认实现:

<?php // Some framework module

function provide_defaults()
{
    // Make sure a critical function exists:
    if (!function_exists("tedious_plugin_callback"))
    {
        function tedious_plugin_callback()
        {
        // Complex code no plugin author ever bothers to customize... ;)
        }
    }
}

在函数中定义的函数我看不到有用但有条件定义的函数我可以。例如:

if ($language == 'en') {
  function cmp($a, $b) { /* sort by English word order */ }
} else if ($language == 'de') {
  function cmp($a, $b) { /* sort by German word order; yes it's different */ }
} // etc

然后你需要做的就是在usort()调用之类的东西中使用'cmp'函数,这样你就不会在代码中乱丢语言。现在我还没有这样做,但我可以看到这样做的论据。

以上所述,人们可能只是简单地创建一个嵌套函数来替换函数中的一些本地化重复代码(只能在父函数中使用)。匿名函数就是一个很好的例子。

有些人可能会说只是在一个类中创建私有方法(或更小的代码块),但是当一个超特定的任务(父母独有的)需要模块化时,这会混淆水域,但不一定可用于其余的课程。好消息是如果事实证明你确实需要在其他地方使用该功能,那么修复就相当基本(将定义移到更中心的位置)。

一般来说,使用JavaScript作为评估其他基于C语言的编程语言的标准是一个坏主意。与PHP,Python,Perl,C,C ++和Java相比,JavaScript绝对是它自己的动物。当然,有很多一般的相似之处,但是细节,细节(参考 JavaScript:The Definitive Guide,第6版,第1-12章),在注意时,使核心JavaScript独一无二,所有这些都是美丽的,不同的,简单的,复杂的。那是我的两分钱。

为了清楚起见,我不是说嵌套函数是私有的。只有当一些微不足道的事情需要模块化时(这只是父函数需要),嵌套可以帮助避免混乱。

我的所有php都是OO,但我确实看到了嵌套函数的用法,特别是当你的函数是递归的而不一定是对象时。也就是说,它不会在嵌套的函数之外调用,而是递归的,随后需要成为函数。

为明确使用单一其他方法制作新方法毫无意义。对我来说,这是笨拙的代码,并不是OO的重点。如果您永远不会在其他地方调用该函数,请将其嵌套。

在webservice调用中,我们发现它的开销(内存和速度)低得多,包括嵌套方式,单个函数超过1000个函数的库。典型的调用堆栈可能在5-10个调用深度之间,只需要动态链接十几个1-2kb文件,这比包括兆字节更好。这只是通过创建一个小的util函数包装需要来完成的。包含的函数嵌套在调用堆栈上方的函数中。与每个webservice调用不需要的100个函数的类相比,它也可以使用php的内置延迟加载功能。

我知道这是一个老帖子,但是当我只需要本地功能时,我会使用嵌套函数为递归调用提供一个干净整洁的方法 - 例如用于构建分层对象等(显然你需要小心,父函数只被调用一次):

function main() {
    // Some code

    function addChildren ($parentVar) {
        // Do something
        if ($needsGrandChildren) addChildren ($childVar);
    }
    addChildren ($mainVar); // This call must be below nested func

    // Some more code
}

php中与JS相比较的一个注意事项是,嵌套函数的调用需要在函数声明之后(即下面)进行(与JS相比,函数调用可以在父函数中的任何位置

如果您使用的是php 7,请参阅: 此实现将为您提供有关嵌套函数的清晰概念。 假设我们有三个函数(too(),boo()和zoo())嵌套在函数foo()中。 boo()和zoo()具有相同的命名嵌套函数xoo()。现在在这段代码中,我已经清楚地评论了嵌套函数的规则。

   function foo(){
        echo 'foo() is called'.'<br>';
        function too(){
            echo 'foo()->too() is called'.'<br>';
        }
        function boo(){
            echo 'foo()->boo() is called'.'<br>';
            function xoo(){
                echo 'foo()->boo()->xoo() is called'.'<br>';
            }
            function moo(){
                echo 'foo()->boo()->moo() is called'.'<br>';
            }
        }
        function zoo(){
            echo 'foo()->zoo() is called'.'<br>';
            function xoo(){     //same name as used in boo()->xoo();
                echo 'zoo()->xoo() is called'.'<br>';
            }
        #we can use same name for nested function more than once 
        #but we can not call more than one of the parent function
        }
    }

/****************************************************************
 * TO CALL A INNER FUNCTION YOU MUST CALL OUTER FUNCTIONS FIRST *
 ****************************************************************/
    #xoo();//error: as we have to declare foo() first as xoo() is nested in foo()

    function test1(){
        echo '<b>test1:</b><br>';
        foo(); //call foo()
        too();
        boo();
        too(); // we can can a function twice
        moo(); // moo() can be called as we have already called boo() and foo()
        xoo(); // xoo() can be called as we have already called boo() and foo()
        #zoo(); re-declaration error
        //we cannont call zoo() because we have already called boo() and both of them have same named nested function xoo()
    }

    function test2(){
        echo '<b>test2:</b><br>';
        foo(); //call foo()
        too();
        #moo(); 
        //we can not call moo() as the parent function boo() is not yet called
        zoo(); 
        xoo();
        #boo(); re-declaration error
        //we cannont call boo() because we have already called zoo() and both of them have same named nested function xoo()

    }

现在,如果我们调用test1(),输出将是:

test1:
foo() is called
foo()->too() is called
foo()->boo() is called
foo()->too() is called
foo()->boo()->moo() is called
foo()->boo()->xoo() is called

如果我们调用test2(),输出将是:

test2:
foo() is called
foo()->too() is called
foo()->zoo() is called
zoo()->xoo() is called

但我们不能同时调用text1()和test2()以避免重新声明错误

我只是在主要的,更加分类的函数中执行一个小的递归函数,但不想将它移动到另一个文件,因为它是主要行为的基础时,才真正使用了这个特性。处理。我意识到还有其他“最佳实践”。这样做的方法,但我想确保我的开发人员每次看到我的解析器时都会看到该函数,它可能是他们应该修改的东西......

嵌套函数在Memoization中很有用(缓存函数结果可以提高性能)。

<?php
function foo($arg1, $arg2) {
    $cacheKey = "foo($arg1, $arg2)";
    if (! getCachedValue($cacheKey)) {
        function _foo($arg1, $arg2) {
            // whatever
            return $result;
        }
        $result = _foo($arg1, $arg2);
        setCachedValue($cacheKey, $result);
    }
    return getCachedValue($cacheKey);
}
?>

如果希望嵌套函数使用在父函数中声明的变量,嵌套函数很有用。

<?php
ParentFunc();
function ParentFunc()
{
  $var = 5;
  function NestedFunc()
  {
    global $var;
    $var = $var + 5;
    return $var;
  };
  echo NestedFunc()."<br>";
  echo NestedFunc()."<br>";
  echo NestedFunc()."<br>";
}
?>
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top