匿名函数
如果只是省去函数名,单纯的当作一个函数式方法返回,只能称为匿名函数(闭包需要将匿名函数当作结果返回),比如:
1 2 3 4 5 var foo = function (x, y ) { return x + y ; }; console .log(foo(1 , 2 ));
1 2 3 4 5 6 <?php $foo = function ($a, $b) { return $a + $b; }; echo $foo(1 , 2 );
闭包
闭包通常是用来创建内部变量,使得这些变量不得被外部随意修改,而只能通过指定的函数接口去修改
js闭包 这里举一个阮老师博客里的例子,阮老师博客:学习Javascript闭包(Closure)
js基础 参考链接:深入理解JS中声明提升、作用域(链)和this
关键字
js比较特殊的一点是:函数内部可以直接读取到全局变量(对于阮老师的这句话不是很能理解,大概是想表达的意思:父作用域的变量可以在子作用域直接访问,而不需要去声明访问真正的全局变量?)
大部分语言,变量都是先声明在使用,而对于js,具有声明提升的特性(不管在哪里声明,都会在代码执行前处理)
函数和变量的声明总是会隐式地被移动到当前作用域的顶部,函数的声明优先级高于变量的声明
var 会在当前作用域声明一个变量,而未声明的变量,会隐式地创建一个全局变量
1 2 3 console .log(a); var a = 1 ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 function testOrder (arg ) { console .log(arg); console .log(a); var arg = 'hello' ; var a = 10 ; function a ( ) { console .log('fun' ); } console .log(a); console .log(arg); }; testOrder('hi' );
1 2 3 4 5 6 7 8 var foo = 42 ;function test ( ) { foo = 21 ; } test(); foo;
1 2 3 4 5 6 7 8 foo = 42 ; function test ( ) { var foo = 21 ; } test(); foo;
js变量的查找是从里往外的,直到最顶层(全局作用域),并且一旦找到,即停止向上查找。所有内部函数可以访问函数外部的变量,反之无效
1 2 3 4 5 6 7 8 function foo (a ) { var b = a * 2 ; function bar (c ) { console .log(a, b, c); } bar(b * 3 ); } foo(2 );
1 2 3 4 function foo ( ) { var a = 1 ; } console .log(a);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function foo1 ( ) { var num = 0 ; addNum = function ( ) { num += 1 ; }; function foo2 ( ) { console .log(num); } return foo2; } var tmp = foo1();tmp(); addNum(); tmp();
这里第二次调用foo2函数,foo1函数的局部变量num并没有被初始化为0,说明打印的是内存中的num。正常函数在每次调用结束后都会销毁局部变量,在重新调用的时候会再次声明变量;而这边没有重新声明的原因是:把foo2函数赋值给了一个全局变量tmp,导致foo2函数一直存在内存中,而foo2函数依赖于foo1函数存在,所以foo1函数也存在内存中,并没有被销毁,所以foo1的局部变量也是存在内存中。
this
的上下文基于函数调用的情况。和函数在哪定义无关,而和函数怎么调用有关。
在全局上下文(任何函数以外),this指向全局对象(windows)
在函数内部时,this由函数怎么调用来确定
下面是阮老师博客里的两个思考题:
1 2 3 4 5 6 7 8 9 10 var name = "The Window" ;var object = { name : "My Object" , getNameFunc : function ( ) { return function ( ) { return this .name; }; } }; alert(object.getNameFunc()());
1 2 3 4 5 6 7 8 9 10 11 var name = "The Window" ;var object = { name : "My Object" , getNameFunc : function ( ) { var that = this ; return function ( ) { return that.name; }; } }; alert(object.getNameFunc()());
this
的作用域好像一直是个比较奇怪的东西,对于上面两个例子,我的理解是:第一个例子,是在方法里调用的this
,而这个this
并没有声明
,会隐式地创建一个全局变量,所以调用的全局的name;第二个,调用的that
的时候,会向顶级链式查找是否声明that
,而这个that有this赋值,这里的this又是通过对象方法调用,则该this指向这个object对象,所有最终调用的是object作用域内的name。不知道这么理解是不是有问题,还望大神指正。
那其实js闭包的主要目的:访问函数内部的局部变量,即延长作用域链 参考链接:js闭包MDN文档
php闭包 php回调函数 [mixed call_user_func ( callable $callback , mixed $parameter [, mixed $… ]] ) mixed call_user_func_array ( callable $callback , array $param_arr )
这两个函数都是把第一个参数作为回调函数d调用,后面接收参数,区别就是第二个函数第二参数接收数组;在使用上唯一的区别就是,call_user_func
函数无法接收引用传递
; 个人觉得同样是使用,call_user_func 相比call_user_func_array完全可以被替代,不知道是不是有一些性能上的优势。具体使用样例,请参考官方文档。
1 2 3 4 5 6 7 8 9 <?php function foo (&$a, &$b) { $a ++; $b --; }; $a = $b = 10 ; call_user_func_array('foo' , [&$a, &$b]); echo $a."\n" , $b;
基本用法 基本用法,跟js的闭包类似
1 2 3 4 5 6 <?php global $tmp = 'hello world' ;function foo () { var_dump(global $tmp); } foo();
1 2 3 4 5 6 7 8 9 10 <?php $foo1 = function () { $a = 10 ; $foo2 = function () { var_dump($a); }; return $foo2; }; $tmp = $foo1(); $tmp();
php想要能够获取上级作用域的变量,需要通过use传递
1 2 3 4 5 6 7 8 9 10 11 12 <?php $foo1 = function () { $a = 10 ; $foo2 = function () use ($a) { var_dump($a); $a ++; }; $foo2(); return $foo2; }; $tmp = $foo1(); $tmp();
1 2 3 4 5 6 7 8 9 10 11 12 <?php $foo1 = function () { $a = 10 ; $foo2 = function () use (&$a) { var_dump($a); $a ++; }; $foo2(); return $foo2; }; $tmp = $foo1(); $tmp();
下面两段代码的区别,不是很明白,望大佬指点,为什么后一个值传递就可以获取到已经改变后变量的值。好像都是在调用方法之前,已经执行过变量的递增了吧?
1 2 3 4 5 6 7 8 9 10 11 12 <?php $foo1 = function () { $a = 10 ; $foo2 = function () use ($a) { var_dump($a); }; $a ++; return $foo2; }; $tmp = $foo1(); $tmp();
1 2 3 4 5 6 7 8 9 10 11 12 <?php $foo1 = function () { $a = 10 ; $foo2 = function () use (&$a) { var_dump($a); }; $a ++; return $foo2; }; $tmp = $foo1(); $tmp();
1 2 3 4 5 6 7 8 9 10 11 <?php $foo = function () { $a = 10 ; $foo2 = function ($num) use ($a) { var_dump($num + $a); }; return $foo2; }; $tmp = $foo(); $tmp(100 );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?php $foo = function () { $a = 10 ; $foo2 = function ($num) use (&$a) { var_dump($num + $a); $a ++; }; return $foo2; }; $tmp = $foo(); $tmp(100 ); $tmp(100 ); $tmp(100 );
php Closure 类
共同点 都是为了扩展作用域,获取内部变量
区别 js能够在方法内部直接获取到父级作用域的变量,而php需要通过use声明,并且默认是值传递
应用场景
不是很能理解应用场景,搜索了一下,很多只是写了一个闭包实现的购物车,感觉并不是那么的实用。
如果只是单纯的使用匿名函数,感觉还不如封装成一个私有方法
这些只是个人粗鄙的理解,望指正.