js 脑补

06 Jan 2016 Category: Javascript

js的变量作用域,根据不同的定义位置分为全局变量以及局部变量。同事, 任何没有用var定义的变量都是全局变量。如果没有局部变量,则寻找全局变量。 但是需要注意一点,函数域优于全局域,当变量调用语句在函数域内,同时函数域中也存在 局部变量,则使用的是局部变量,不管调用时,变量是否定义。


var a = 123;//全局变量
function test(){
    alert(a);//弹出undefined,因为此时局部变量a还为定义;
    var a = 1;
    alert(a);//弹出1;
}

如果把函数中var a = 1;注释掉,则会弹出两次123

函数和闭包


function test()
{
    var a = [];
    var i = 0;
    for(i=0;i<3;i++)
    {
        a[i] = function(){
            return i;
        }
    }
    return a;
}

var f = test();
console.log(f[0]);//输出3
console.log(f[1]);//输出3
console.log(f[2]);//输出3

控制台输出 3,3,3

说明: a[i],这里的i是循环的时候就已经确定了。


function(){
    return i;
}

这里的i是test函数执行完之后,即循环三次之后的i,因此i=3;

如果想要是想a[0] = 0;需要在函数定义的时候,将i作为参数传入函数中。


function test()
{
    var a = [];
    var i = 0;
    for(i=0;i<3;i++)
    {
        a[i] = (function(x){
            return x;
        })(i)
    }
    return a;
}

var f = test();
console.log(f[0]);//输出0
console.log(f[1]);//输出1
console.log(f[2]);//输出2

查看更多

PHP 松散比较的几个值

04 Jan 2016 Category: PHP

PHP中几个比较容易混乱的值:false,’0’,0,’‘,null,array().这几个值在if判断中都是false,那么他们之间相互进行’==’比较呢?

一下是这几个值的比较结果:

  0 ‘0’ false ’’ null array()
0 true true true true true false
‘0’ true true true false false false
false true true true true true true
’’ true false true true true false
null true false true true true true
array() false false true false true true

php按一下顺序进行比较运算:

  • null或string与string比较,先转换成string再比较

  • bool和null与其他任何类型比较,转换成bool

  • string和number相互比较,先转换成数字类型

  • bool与任何其他类型比较,先转换成bool值

  • array和任意其他类型比较,或其他类型与数组比较,都是数组大。所以0 == array 是false

查看更多

PHP 数组相加与array_merge的区别

01 Jan 2016 Category: PHP

PHP合并数组可以使用”+”号或者array_merge函数。那么这两个不同的方式有什么区别呢?

  • 数字键名的情况
$a = ["php","java"];
$b = ["c++","python","vb"];

var_dump($a+$b);//输出["php","java","vb"]
var_dump(array_merge($a,$b));["php","java","c++","python","vb"]

数字键的时候,两个数组相加,如果键名相同,留先出现的,后面的不要。array_merge是吧两个数组完全合并在一起

  • 字符串键名的情况
$a = ["name"=>"Lili","sex"=>0];
$b = ["name"=>"LiHao","sex"=>1,"age"=>22];
var_dump($a+$b);//输出["name"=>"Lili","sex"=>0,"age"=>22]
var_dump(array_merge($a,$b));//输出["name"=>"LiHao","sex"=>1,"age"=>22];

字符串键名数组相加也是取首先出现的数组做最后的结果。array_merge是后面的数据覆盖前面的数据。

查看更多

PHP 盲点扫描 01

31 Dec 2015 Category: PHP

PHP语言由于其语法简单,没有数据类型,因此会有不少不易被发现的盲点,这些盲点一旦在 应用中出现,非常具有隐蔽性,很难发现,因为很多都会让你觉得不科学。但是,当你 仔细阅读PHP手册,还真是这样。

  • 1.PHP中,对一个null值,用数组的方式获取元素,不报错。但是对一个空数组获取不存在的元素会报错。
$a = null;
var_dump($a['tttt']);//输出null,不报错。

$b = array();
var_dump($b['tttt']);//throw exception undefiend index
  • 2.php中会对字符串数学运算会对字符串进行转换,按十进制方式
$x = 0123;          // 八进制,相当于十进制83
$y = "0123" + 0     // 十进制123
  • 3.字符串在和数字数学运算或者比较中都会进行类型转换。

  • 4.PHP魔术变量

    _FUNCTION_ and _METHOD_ as in PHP 5.0.4 is that _FUNCTION_ returns only the name of the function while as _METHOD_ returns the name of the class alongwith the name of the function

<?php
namespace test\example;
class Obj {
    function test() {
        echo __FILE__ . "<br/>"; //绝对路径
        echo __LINE__ . "<br/>"; //行号
        echo __NAMESPACE__ . "<br/>"; //完整命名空间test\example
        echo __FUNCTION__ . "<br/>"; //当前函数名称test
        echo __METHOD__ . "<br/>"; //带命名空间的类方法test\example\Obj::test
        echo __CLASS__ . "<br/>"; //带命名空间的类test\example\Obj
    }
}
$obj = new Obj();
$obj::test();
?>
  • 5.__CLASS__和get_class($this)

<?php

class base_class
{
    function say_a()
    {
        echo "'a' - said the " . __CLASS__ . "<br/>";
    }

    function say_b()
    {
        echo "'b' - said the " . get_class($this) . "<br/>";
    }

}

class derived_class extends base_class
{
    function say_a()
    {
        parent::say_a();
        echo "'a' - said the " . __CLASS__ . "<br/>";
    }

    function say_b()
    {
        parent::say_b();
        echo "'b' - said the " . get_class($this) . "<br/>";
    }
}

$obj_b = new derived_class();

$obj_b->say_a();
echo "<br/>";
$obj_b->say_b();

?>

输出结果:

'a' - said the base_class
'a' - said the derived_class

'b' - said the derived_class
'b' - said the derived_class

__CLASS__获取的是__CLASS__所在的类的类名 getclass($this)是获取当前类的类名.

  • 6.PHP 子类中调用父类函数,父类函数中的$this到底指谁?
<?php

class MyParent {
    public $name = 'parent';
    function test() {
        var_dump($this);
        echo $this->name . "<br/>";
    }
}

class Child extends MyParent {
    public $name = 'child';
    function test() {
        parent::test();
        echo $this->name . "<br/>";
    }
}

$parent = new MyParent();
$parent->test();

$child = new Child();
$child->test();
?>

输出结果

object(MyParent)#1 (1) { ["name"]=> string(6) "parent" } parent
object(Child)#2 (1) { ["name"]=> string(5) "child" } child
child
  • 7.递增/递减运算符不影响布尔值。递减 NULL 值也没有效果,但是递增 NULL 的结果是 1。字符串的自增自减,如果不能转换成合法的数字,则根据ASCII码进行
$a = "012";
$b = "AA";

for($i=0;$i<5;$i++)
{
    echo ++$a;//输出13,14,15,16,17
    echo ++$b;//输出AB,AC,AD,AE,AF
}

查看更多

Yii2 PHP 手册阅读记录

18 Dec 2015 Category: PHP

  • action的默认参数都是从$_GET中获取

The action methods for inline actions and the run() methods for standalone actions can take parameters, called action parameters. Their values are obtained from requests. For Web applications, the value of each action parameter is retrieved from $_GET using the parameter name as the key; for console applications, they correspond to the command line arguments.

  • 如果action的默认参数要传一个数组,需要在参数前添加限定符array

If you want an action parameter to accept array values, you should type-hint it with array

public function actionView(array $id, $version = null)
{
    // ...
}
  • action的寻找顺序,匹配

查看更多

Android FragmentTabhost 截断tab点击事件

17 Dec 2015 Category: Developer

Android FragmentTabhost 可以很方便的实现tabhost布局,但是如果一个场景: 某个tab需要验证用户登录才能够显示,如果用户没登录,跳转到登陆activity。这个时候 就需要截断tab的点击事件。

以上面的场景为例

mTabHost.getTabWidget().getChildTabViewAt(needInteraptTab).setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
       if(isLogin())
       {
            //如果已经登录,执行默认点击操作
            //由于已经覆写了点击方法,所以需要实现tab切换
           mTabHost.setCurrentTab(count-1);
           mTabHost.getTabWidget().requestFocus(View.FOCUS_FORWARD);
       }
       else
       {
            //如果没有登陆
           Intent intent = new Intent();
           intent.setClass(context,LoginActivity.class);
           startActivity(intent);
       }
   }
});

上面就实现了tab点击前判断用户是否登陆,并根据登陆状态执行不同的操作。

查看更多

PHP面向对象深入--构造函数中调用成员函数,到底调用的是哪个类的函数

15 Dec 2015 Category: PHP

PHP中,静态方法中不能使用$this,即用双冒号::调用的函数。这里,构造函数要除外,那么, 构造函数中的$this到底指向谁,$this->display函数又会执行那个类里面的函数?

如果去看Yii2的源码,发现Yii2的源码都是在构造函数中调用一个init函数对类进行初始化 的操作。但是如果看Application.php的源码,发现在构造函数__construct里面并没有显示 的调用init函数,也没有调用其父类的构造函数,而是调用Compoment的构造函数,继续追踪, 发现Application 继承 Module, Module继承ServiceLocator, ServiceLocator继承Component, Component继承Object, 而在Object的构造函数中调用了init函数。

    public function __construct($config = []) {
        if (!empty($config)) {
            Yii::configure($this, $config);
        }
        $this->init();
    }

那么,这里的$this指向Application还是Object本身呢?为此,用下面的程序进行试验 从结果可以看出,$this指向的是调用者本身。 如果父类的display方法是public或者protected(即可以被子类继承),执行的是调用类,否则 就是当前所在类的成员函数。但是这种情况下,display函数里面打印$this依然是调用类。


<?php
class MyObj {

    function __construct() {
        $this->display();
        var_dump($this);//输出MyApp
    }

    public function display(){//修饰符是private的时候执行该函数,否则执行子类函数
        var_dump($this);//输出MyApp,无论方法修饰符是private 还是public,protected
        echo 'obj';
    }

}
class Modle extends MyObj {

}

class Compoment extends Modle {

}
class MyApp extends Compoment {
    function __construct() {
        Modle::__construct();
    }

    public function display(){//
        echo 'obj test public';
    }
}

$objOther = new MyApp();
?>

理解(此处仅仅是个人理解) :

  • 如果父类的diplay函数是可以被继承的,且子类中重写了该函数,则调用的是子类 的display函数。其他情况,不可继承或子类并没与重写该函数,执行父类函数。

  • 对于$this的指向,$this总是指向最终构造的对象。因为这是构造函数。

查看更多

Node.JS 回调函数在请求已经结束之后是否会执行?

14 Dec 2015 Category: Developer

做PHP,程序都是顺序执行的,所谓回调函数,其本身也是顺序执行的。但是Node.js 本身是 回调函数是异步执行的。PHP中,如果请求结束,那么在改请求所执行的操作都结束了。那么 Node.js里呢。

我想用node.js搭建一个服务程序,然后采集其他站点的数据,因为很多站点的数据都需要js 解析。那么问题来了,我通过linux cron 定时访问node服务,node服务向我要采集的站点 发起网络请求,并在网络请求的回调中完成数据采集的操作。那我的node服务是要等待数据采 集完才给出请求反馈么?如果我需要在一次cron 访问中采集多个站点的数据,那么,等待这些 异步采集全部执行完再返回吗?如果我发起调用万采集函数之后,直接返回cron结果,通知 cron请求已经被执行了,已经发起的采集请求还会执行到回调函数里吗?这就是题目中的问题, Node.JS 回调函数在请求已经结束之后是否会执行?

当然,答案是肯定的(已经试验过了)。Node.js的异步进程(或线程,此处并不确定是哪个), 并不是随着浏览器的访问的结束而结束。每个http请求和http请求中所发起的其他操作都是 平级的,并没有从属关系,Node.js本身维护这些进程,因此除非node服务down了,否则回调 都会执行。

对比PHP,如果用PHP抓取多个页面,那么PHP就得等待所有抓取工作完成之后才能够通知执行人, 已经执行了抓取工作。但是,数据抓取本身就有很多的不确定性,如果人家更新了站点, 更新了域名,或者某个站点请求时间长都会造成PHP本身请求超时。但是Node.js 就可以完全非 阻塞的运行,只要发出抓取请求就可以通知执行者已经成功执行了抓取请求。

查看更多