一、闭包基本用法
闭包(Closure)又叫做匿名函数,也就是没有定义名字的函数。比如下面的例子:
// 定义一个闭包,并把它赋给变量 $f
$f = function () {
return 7;
} // 使用闭包也很简单
$f(); //这样就调用了闭包,输出 7 // 当然更多的时候是把闭包作为参数(回调函数)传递给函数
function testClosure (Closure $callback) {
return $callback();
} // $f 作为参数传递给函数 testClosure,如果是普遍函数是没有办法作为testClosure的参数的
testClosure($f); // 也可以直接将定义的闭包作为参数传递,而不用提前赋给变量
testClosure (function () {
return 7;
}); // 闭包不止可以做函数的参数,也可以作为函数的返回值
function getClosure () {
return function () { return 7; };
} $c = getClosure(); // 函数返回的闭包就复制给 $c 了
$c(); // 调用闭包,返回 7
二、闭包类(Closure)
定义一个闭包函数,其实是产生了一个闭包类(Closure)的对象,Closure类摘要如下:
Closure {
public static Closure bind (Closure $closure , object $newthis [, mixed $newscope = 'static' ])
public Closure bindTo (object $newthis [, mixed $newscope = 'static' ])
}
方法说明:
Closure::bind: 复制一个闭包,绑定指定的$this对象和类作用域。
Closure::bindTo: 复制当前闭包对象,绑定指定的$this对象和类作用域。
下面将介绍Closure::bind和Closure::bindTo
参数和返回值说明:
closure:表示需要绑定的闭包对象。
newthis:表示需要绑定到闭包对象的对象,或者NULL创建未绑定的闭包。
newscope:表示想要绑定给闭包的类作用域,可以传入类名或类的示例,默认值是 'static', 表示不改变。
该方法成功时返回一个新的 Closure 对象,失败时返回FALSE。
class Animal {
private static $cat = "cat";
private $dog = "dog";
public $pig = "pig";
} /*
* 获取Animal类静态私有成员属性
*/
$cat = static function() {
return Animal::$cat;
}; /*
* 获取Animal实例私有成员属性
*/
$dog = function() {
return $this->dog;
}; /*
* 获取Animal实例公有成员属性
*/
$pig = function() {
return $this->pig;
}; $bindCat = Closure::bind($cat, null, new Animal());// 给闭包绑定了Animal实例的作用域,但未给闭包绑定$this对象
$bindDog = Closure::bind($dog, new Animal(), 'Animal');// 给闭包绑定了Animal类的作用域,同时将Animal实例对象作为$this对象绑定给闭包
$bindPig = Closure::bind($pig, new Animal());// 将Animal实例对象作为$this对象绑定给闭包,保留闭包原有作用域
echo $bindCat(),'<br>';// 根据绑定规则,允许闭包通过作用域限定操作符获取Animal类静态私有成员属性
echo $bindDog(),'<br>';// 根据绑定规则,允许闭包通过绑定的$this对象(Animal实例对象)获取Animal实例私有成员属性
echo $bindPig(),'<br>';// 根据绑定规则,允许闭包通过绑定的$this对象获取Animal实例公有成员属性 // bindTo与bind类似,是面向对象的调用方式,这里只举一个,其他类比就可以
$bindCat = $cat->bindTo(null, 'Animal');
最后举一个PHP官网给出的例子
class A {
function __construct($val) {
$this->val = $val;
}
function getClosure() {
//returns closure bound to this object and scope
return function() { return $this->val; };
}
} $ob1 = new A(1);
$ob2 = new A(2); $cl = $ob1->getClosure();
echo $cl(), "\n";
$cl = $cl->bindTo($ob2);
echo $cl(), "\n";
以上示例输出:
1
2
 
 
 

PHP 闭包的更多相关文章

  1. 《Web 前端面试指南》1、JavaScript 闭包深入浅出

    闭包是什么? 闭包是内部函数可以访问外部函数的变量.它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量. 内部函数不仅可以访问外 ...

  2. 干货分享:让你分分钟学会 JS 闭包

    闭包,是 Javascript 比较重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,很难从定义去理解它.因此,本文不会对闭包的概念进行大篇幅描述 ...

  3. 深入浅出JavaScript之闭包(Closure)

    闭包(closure)是掌握Javascript从人门到深入一个非常重要的门槛,它是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现.下面写下我的学习笔记~ 闭包-无处不 ...

  4. javascript之闭包理解以及应用场景

    半个月没写博文了,最近一直在弄小程序,感觉也没啥好写的. 之前读了js权威指南,也写了篇博文,但是实话实说当初看闭包确实还是一头雾水.现在时隔一个多月(当然这一段时间还是一直有在看闭包的相关知识)理解 ...

  5. js闭包 和 prototype

    function test(){ var p=200; function q(){ return p++; } return q; } var s = test(); alert(s()); aler ...

  6. js闭包for循环总是只执行最后一个值得解决方法

    <style> li{ list-style: none;width:40px;height: 40px;text-align:center;line-height: 40px;curso ...

  7. JavaScript学习笔记(二)——闭包、IIFE、apply、函数与对象

    一.闭包(Closure) 1.1.闭包相关的问题 请在页面中放10个div,每个div中放入字母a-j,当点击每一个div时显示索引号,如第1个div显示0,第10个显示9:方法:找到所有的div, ...

  8. 带你一分钟理解闭包--js面向对象编程

    上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...

  9. 如何设计一门语言(七)——闭包、lambda和interface

    人们都很喜欢讨论闭包这个概念.其实这个概念对于写代码来讲一点用都没有,写代码只需要掌握好lambda表达式和class+interface的语义就行了.基本上只有在写编译器和虚拟机的时候才需要管什么是 ...

  10. JavaScript 闭包深入浅出

    闭包是什么? 闭包是内部函数可以访问外部函数的变量.它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量. 内部函数不仅可以访问外 ...

随机推荐

  1. java代码示例(3)

    /** * 需求分析:根据输入的天数是否是周六或是周日, * 并且天气的温度大于28摄氏度,则外出游泳,否则钓鱼 * @author chenyanlong * 日期:2017/10/14 */ pa ...

  2. Git-Credential-Manager-for-Mac-and-Linux

    1.安装brew 安装命令: /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/instal ...

  3. 为什么要用redis

    服务端的程序如何去识别客户端的状态: http是没有状态的,比如说用户A访问了服务器程序,那服务器如何知道下一次访问的时候还是A呢,这里就要用到session, 这个session是服务器的sessi ...

  4. javascript 模块化规范

    服务器端规范 - CommonJS Node.js 浏览器端规范 - AMD RequireJS - CMD SeaJS

  5. (五)bootloader 启动 ucore os

    Lab1 : bootloader 启动 ucore os 一.内容提要 x86启动顺序 C函数调用 gcc内联汇编(inline assembly) x86-32下的中断处理 小结 二.x86启动顺 ...

  6. Jena搭建SPARQL查询RDF数据

    1 Jena搭建SPARQL查询RDF数据 1.1 Jena概要 · SPARQL是W3C的RDF数据工作组设计的一种查询语言和协议,用于RDF数据的查询.经过类似于JDK安装时候的配置,可以在命令行 ...

  7. luogu 1006 传纸条

    三/四维dp,将两次传递均看作从左上而来,在dp过程中注意防止越界/重合 f[i][j][k][l]直接枚举两轮的点,如下 #include<bits/stdc++.h> #define ...

  8. pandas 读csv文件 TypeError: Empty 'DataFrame': no numeric data to plot

    简单的代码,利用pandas模块读csv数据文件,这里有两种方式,一种是被新版本pandas遗弃的Series.from_csv:另一种就是pandas.read_csv 先说一下问题这个问题就是在读 ...

  9. luogu P2516 [HAOI2010]最长公共子序列

    传送门 首先那个\(O(n^2)\)的dp都会吧,不会自己找博客或者问别人,或是去做模板题(误) 对以下内容不理解的,强势推荐flash的博客 我们除了原来记录最长上升子序列的\(f_{i,j}\), ...

  10. Java 的NIO 3个主要概念 Channel、Buffer、Selector

    Java 的NIO 3个主要概念 Channel.Buffer.Selector,为何提高了性能