首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >对$this的动态引用应该不起作用,但它确实起作用了

对$this的动态引用应该不起作用,但它确实起作用了
EN

Stack Overflow用户
提问于 2015-02-10 05:40:38
回答 1查看 3.9K关注 0票数 54

根据PHP中关于Variable variables的文档:

$this是不能动态引用的特殊变量

然而,它似乎是错误的,至少在我测试过的PHP版本(5.5.12)上是这样。

代码语言:javascript
复制
class ThisIsBugged
{
    public function __construct()
    {
        ${'this'}->doSomething(); // This works, while it shouldn't
    }
}

问题#1:它是如何工作的?根据文档,它不应该。

但还有更多。

代码语言:javascript
复制
class ThisIsBugged
{
    public function __construct()
    {
        // This does not work, but it could. See below.
        ${'th' . 'is'}->doSomething();
    }
}

它会像预期的那样停止执行:

PHP注意事项:未定义变量: this

致命错误:在非对象上调用成员函数doSomething()。

注意,语句{'th' . 'is'}的计算结果是:“未定义的变量: this”。

然而(这是最奇怪的事情),显式引用特殊变量$this,修复了方法中在该变量之前或之后使用的所有动态引用。

代码语言:javascript
复制
class ThisIsBugged
{
    public function __construct()
    {
        // Now it works while it shouldn't
        ${'th' . 'is'}->doSomething();

        // This fixes both the previous and the subsequent calls
        $unused = $this;

        // Now it works while it shouldn't
        ${'th' . 'is'}->doSomething();
    }
}

问题#2:显式引用$this如何修复整个方法中存在的对$this的所有其他动态引用?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-02-10 06:19:07

PHP使用了一个我们称之为编译变量(CV)优化的概念。这意味着,我们不使用将变量名映射到它们的值的哈希表,而是使用普通数组并对其进行索引。编译器知道哪个变量名对应于哪个索引。执行数组索引查找比执行哈希表查找快得多。

$this变量也将以这种方式存储,并且它的索引被特别地记为op_array->this_var。如果未找到$this使用,则在-1中保留该值为未初始化状态。在将新的执行上下文推送到VM堆栈时,PHP将检查op_array->this_var,如果不是-1,则初始化$this变量条目。

当一个变量被访问时,PHP将遍历CV表,并根据它构造一个适当的符号哈希表。当然,它只会添加实际上在CV表中的变量,所以如果它不包含$this,那么您将得到一个未定义的变量查找。

现在考虑你的三个案例:

  • 因为PHP5.x编译器还没有执行常量表达式折叠,所以它不能检测到${"th"."is"}也是一个$this访问。因此,this_var在最后一种情况下保持uninitialized.

  • In,因为这样的$this将被设置,并且也可以通过变量-变量查找来访问。

注意,在PHP7中情况是不同的-我们总是在变量变量查找上设置this_var,所以间接$this查找应该总是有效的。

票数 70
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28419924

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档