最近招PHP出的一道面试题

2,694 views

有简单的地方, 也有坑的地方。 但是基本上没有能答得让我比较满意。

分享下题目,如果有什么不合适的, 请指出来谢谢

你觉得下面的3个var_dump会输出什么,如果你是作者,在代码上,你会怎么修改到你觉得满意的程度?

Screenshot from 2014-02-19 22:10:37

 

Screenshot from 2014-02-19 22:11:30

 

 

 

我分享下我想要的答案:

1 在 protected $_a 这行,  把$_a变量修改成至少是拼音。。。中式英语也行。。。 best: $_interviewCount,相应的下面用到$_a的代码也一并改掉

2 构造函数public function Interview , 这样的同名构造函数, 虽然现在PHP5向下兼容, 但是会给程序带来维护的复杂度, 因为修改类名的时候, 还得再修改构造函数的名字。  改成 __constructor 不仅在语义上更好,而且降低了维护成本

3 getInterviewCount的静态方法里,

 

if的花括号至少应该和整个文件的风格统一, 应该要换行。

而且代码我觉得最好的方式应该改成

return $this->_a  ? $this->_a : $this->_a * 5;

另外, 如果PHP版本在5.4+的话,最好改成

return $this->_a  ? : $this->_a * 5;

只需要一行即可,既修掉了花括号的问题, 也考察了对PHP版本带来的更好性能的新变化的认识。

 

4 文件应该把最后的?>取消掉, 在?>后的换行和空格会给程序带来隐患, 具体隐患相信每个PHPer都知道

5 第一个var_dump输出并不是1或者5, 而是报错 Fatal error: Using $this when not in object context in xxx

因为getInterviewCount方法是静态方法, 静态方法可以直接调用, 不需要实例化, 因此没有实例化也就不存在$this了,也无法访问。 因此代码改成

return self::$_a ? : self::$_a * 5;此时,并没有完, 想要访问到$_a, 还必须把$_a改成静态变量

这时候输出0, 因为$_a并没有被构造函数初始化, 在执行乘法的时候PHP有一次强制转换, 变成 0 * 5

6 第二个var_dump输出2, 方法里注明$arg参数是传引用。当$arg给$return赋值的时候,这个赋值操作只是简单的赋值操作, 这里会有一次写时分离的操作在PHP内部, 把$arg指向的zval结构体分离出一份单独给$return, $return 的引用计数是 refcount=1, is_ref=0 , 而不是 refcount = 3, is_ref = 1, 即$return不会也是外部$test的引用. $arg还会保持原来的refcount = 2, is_ref = 1 , 当$arg + 1的时候, 外部的$test也+1,但是$return的值是2

7 第三个var_dump输出的是1,6

当走到global $var 和global $var2 的时候, 函数内部的$var, $var2虽然和外部的$var, $var2变量名相同, 但是其实它们是存在于不同的符号表里的, 理应是不同的作用域, 但是因为有了global, 这个声明会将函数内部的$var作为外部$var的引用, $var2同理。 当 $var2 = &$var发生的时候, $var2原来引用了外部的$var2内存地址, 现在变成引用$var的内存地址, 此时函数内部的$var,$var2和外部的$var内存地址相同, 当$var2 = 1;的时候,  函数内部的 $var, $var2和外部的$var 都变成1 ,外部的$var2仍然是6 。 各个变量的计数器变化如下

刚开始, 外部的$var, $var2 计数器都是 refcount=1, is_ref=0, 走到两个global完后, 外部和函数内部的$var, $var2计数器都变成 refcount=2, is_ref=1, $var2 = &$var的时候以及走到$var2 = 1,内部 $var2 和 $var和外部的$var 都是 refcount=3, is_ref=1, 外部的$var2 变回 refcount = 1, is_ref = 0 。

 

####

最近开了个技术群, 有兴趣的朋友进来吹牛逼吧, QQ群号221073018

Leave a Reply

Your email address will not be published.