PHP 相当于 JavaScript 绑定

PHP equivalent of JavaScript bind

本文关键字:绑定 JavaScript 相当于 PHP      更新时间:2023-09-26

首先请原谅我的英语,我不是母语人士,如果它看起来很粗糙,很抱歉,这是我第一次在这个网站上发布。我认为我的问题很简单。假设我们有:

class A {
    function foo() {
        function bar ($arg){
            echo $this->baz, $arg;
        }
        bar("world !");
    }
    protected $baz = "Hello ";
}
$qux = new A;
$qux->foo();

在此示例中,"$this"显然不是指我的对象"$qux"。

我应该怎么做才能让它引用"$qux"?

就像在JavaScript中一样: bar.bind(this, "world !")

PHP 没有嵌套函数,所以在你的例子中bar本质上是全局的。你可以通过使用闭包(=匿名函数)来实现你想要的,它从 PHP 5.4 开始支持绑定:

class A {
    function foo() {
        $bar = function($arg) {
            echo $this->baz, $arg;
        };
        $bar->bindTo($this);
        $bar("world !");
    }
    protected $baz = "Hello ";
}
$qux = new A;
$qux->foo();

UPD:但是,bindTo($this)没有多大意义,因为闭包会自动从上下文中继承this(同样,在 5.4 中)。所以你的例子可以很简单:

    function foo() {
        $bar = function($arg) {
            echo $this->baz, $arg;
        };
        $bar("world !");
    }

UPD2:对于 php 5.3 - 这似乎只有像这样丑陋的黑客才能实现:

class A {
    function foo() {
        $me = (object) get_object_vars($this);
        $bar = function($arg) use($me) {
            echo $me->baz, $arg;
        };
        $bar("world !");
    }
    protected $baz = "Hello ";
}

在这里,get_object_vars()用于"发布"受保护/私有属性,使其在关闭中可访问。

实际上,$this在该上下文中调用时确实指的是$qux

您不能在对象方法以外的上下文中使用$this,因此,如果您采用如下内容:

function test() {
    echo $this->baz;
}

无论你做什么,它都行不通。

这种

方式有点奇怪,但是如果你在函数内部使用函数,那么当然一些闭合符是有效的。你可以在 JavaScript 中遇到类似的问题。我建议根本不使用它们,但如果出于某种原因您不想使用它们,那么我会尝试这样(未经测试):

class A {
    function foo() {
        $that = $this;
        function bar ($arg){
            echo $that->baz, $arg;
        }
        bar("world !");
    }
    protected $baz = "Hello ";
}
$qux = new A;
$qux->foo();

更新如果嵌套函数充当全局函数,那么如果需要使用它,您可以将对象作为参数传递:

函数 foo() {

        function bar ($o,$arg){
            echo $o->baz, $arg;
        }
        bar($this,"world !");
    }

如果我理解你想要实现的目标,它可能是这样的:

<?php
class Foo {
  public $prop;
  public function __construct($prop) {
    $this->prop = $prop;
  }
  public function __call($name, $arguments) {
    if (!isset($this->$name)) {
      throw new InvalidArgumentException("No such property: $name");
    }
    if (! $this->{$name} instanceof Closure) {
      throw new InvalidArgumentException("{$name} is not a closure");
    }
    $c = $this->{$name}->bindTo($this);
    return $c(...$arguments);
  }
}
$f = new Foo("bar");
$f->bar = function ($arg) {
  print_r([$arg, $this->prop]);
};
$f->bar("A");
?>

这样,您基本上可以对类中的任何函数进行猴子修补,并像本地函数一样调用它,甚至包括使用$this。但是,有两个限制:

  • 这似乎毫无意义,因为特征是可用的,除非您在不可修改的包上添加真正动态定义的
  • 尽管闭包可以访问 $this 上的属性,但它仍然是对象的外部,因此只能访问公共属性。尝试访问protected/private属性将失败。