【javascript/PHP】当一个JavaScripter初次进入PHP的世界,他将看到这样的风景
本文将从以下11点介绍javascript和PHP在基础语法和基本操作上的异同:
1.数据类型的异同
2.常量和变量的定义的不同,字符串连接运算符不同
3.对象的创建方法的不同
4.PHP与JS在变量声明提升和函数声明提升的差异
5.var在JS和PHP中使用的差异
6.PHP和JS在访问对象属性时候使用的操作符不同
7.类型检测的方式不同
8.论PHP和JS打印变量的方式的对比
9.PHP和JS中函数作用域和全局作用域的关系
10.引用传递还是值传递?
11.JS和PHP对 “数组 ==数组”这一表达式截然不同的对待
1.数据类型不同
JS:基本类型:string,number,boolean,null,undefined 引用类型:object, array,function,
(date,RegExp)
PHP:标量类型:string,float,integer,Boolean,复合类型:object,array 特殊类型:null,Resource
【注意】
• PHP里没有Function类型和undefined类型!虽然PHP定义和使用的函数和JS类似,但在这里函数在类型上只能归为Object类型。同时undefined类型也是不存在的
• Resource即资源类型变量,它保存有为打开文件、数据库连接、图形画布区域等的特殊句柄
2.常量和变量的定义不同,字符串连接运算符不同
对JS变量定义:var A =1 或let A =1; 常量定义:const A = 1;(ES6)
对PHP变量定义:在变量名称前加$ 常量定义: define(变量名称[字符串], $value[常量的值])
<?php define('a', '我是常量');//定义常量 $b = '我是变量'//定义变量 ?>
【注意】在PHP中使用变量和常量的区别在于变量在需要在前面加$,常量不需要
字符串连接要用“.”操作符而不是“+”操作符
JS:var str = '外婆的' + '彭湖湾';
PHP:在PHP中连接字符串时候,我们不能像JS中使用我们喜闻乐见的“+”运算符了
<?php var_dump( '外婆的'+'彭湖湾'); ?>
运行结果:
如你所见,当你试图这样做的时候,它只会返回0
而当你改成:
<?php var_dump( '外婆的'.'彭湖湾'); ?>
3.对象的创建方法不同——在PHP中你无法使用在JS中司空见惯的对象字面量
JS中你可以这样定义对象var person = {name:'penghwuan'}
在PHP中上述做法是种语法错误:
<?php $obj = {name:'penghwuan'}; var_dump($obj); ?>
如果你非要用对象字面量呢?你可能要这样用:(下面只是示范,不推荐)
<?php $obj_text = '{"name":"penghwuan"}';//定义一个字面量形式的字符串 $obj = json_decode($obj_text);//将字符串解析成JSON对象 var_dump($obj);//打印对象 ?>
运行结果:
那么在PHP中应该怎么创建对象呢?——定义一个类并实例化对象
<?php class obj { var $name = '彭湖湾';//定义成员变量 var $hometown = '广东梅州';//定义方法 public function get_name(){ return $this->name; } } $person = new obj;//实例化对象 $hometown = $person->hometown;//通过对象访问成员变量 $name = $person->get_name();//通过对象调用方法 echo '我叫'.$name; echo "<br/>"; echo '我来自'.$hometown;
?>
4.变量声明提升和函数声明提升
JS中最让我们印象深刻的特点是它变量声明提升和函数声明提升的特点,在解析所有代码前,编译器会优先将所有的函数声明和变量声明执行一遍,然后再执行具体的代码。
JS:存在变量和函数声明提升
首先先说一下变量声明提升,而在这之前,先问大家一个问题,如果我们输出一个没有定义的变量会怎么样?
<script type="text/javascript"> console.log(bless);//输出一个尚且不存在的变量 </script>
运行:
没错,会抛出变量未定义的错误。如果我在输出语句的下方加个声明呢?
<script type="text/javascript"> console.log(bless);//输出一个尚且不存在的变量 var bless = '鸡年大吉' </script>
根据猜测,可能的结果三种:
1还是报错
2打印undefined
3打印“鸡年大吉”
demo:
结果是undefined,已经不会报错了,但也并没有被赋值为“鸡年大吉”,这告诉我们两个结论:
1.JS中存在变量声明提升,var声明的变量会被提升至代码顶部执行(在下方声明后不报未定义的错了)
2.JS中虽然存在变量声明提升,但赋值操作却不能被提升(输出undefined而不是鸡年大吉)
根据上述两点的结论,
console.log(bless);//输出一个尚且不存在的变量
var bless = '鸡年大吉'
等价于:
var bless;//变量声明被提升
console.log(bless);//输出一个尚且不存在的变量
bless = '鸡年大吉';//赋值操作未被提升
再说一下函数变量提升:
<script type="text/javascript"> send_bless(); function send_bless(){ console.log('祝你鸡年大吉吧!') } </script>
在声明一个函数前调用这个函数
这就是函数声明提升
PHP:对PHP,存在函数声明提升,但不存在变量声明提升,让我们看一下下面这个例子:
<?php echo $bless;//提前输出变量 send_bless();//提前调用函数 $bless = '鸡年大吉';//定义变量 function send_bless(){//通过声明方式定义函数 echo '祝你鸡年大吉吧'."<br/>"; } ?>
结果是什么呢?
这告诉我们,PHP里面存在函数声明提升,而不存在变量声明提升
5.关于var——在PHP中,你差不多可以忘记var了
我相信这三个var字母已经被无数JSer书写过无数次了,但在PHP中还能不能用var呢?能!但var已经被“打入冷宫,沦为摆设”
JS: var 变量 = 变量值
PHP:在PHP中var只能放在类中,起到声明成员变量的作用,放在类以外的地方就会报错:
<?php var $word = '算法要学好'; echo $word; ?>
运行:
在类中使用就不会报错啦!
<?php class Person{ var $word ='算法要学好'; } $me = new Person(); echo $me->word; ?>
6.访问对象属性时候使用的操作符不同
JS:使用“.”操作符
<script type="text/javascript"> var obj = {name:'彭湖湾'}; console.log(obj.name); </script>
PHP:使用“->”操作符
<?php class Person{ var $word ='算法要学好'; function echo_word(){ echo '数据结构也很重要'; } } $me = new Person(); echo $me->word;//通过->访问对象中的成员变量 echo "<br/>"; echo $me->echo_word();//通过->调用对象中的方法
?>
7.类型检测的方法不同
在类型检测的方法中,我们一般将方法分成两个思路:
思路1:检测变量属于哪种类型。(返回string)
思路2:检测变量是否属于给定类型,(返回boolean)
基于这一思路我来阐述JS和PHP的类型检测机制:
对JS:
思路1:typeof 变量 检测变量类型,能够检测所有JS基本类型(除了null),也能检测出引用类型中的function和Object,缺陷:不能检测出Array和普通对象,而会把它们都检测为Object
<script type="text/javascript"> var number =1,str ='字符串',bool =true,null_value = null,undefined_value =undefined; var fuc = function(){}, array = [1,2,3],obj ={}; console.log('number的类型是',typeof number); console.log('str的类型是',typeof str); console.log('null_value的类型是',typeof null_value); console.log('undefined_value的类型是',typeof undefined_value); console.log('fuc的类型是',typeof fuc); console.log('array的类型是',typeof array); console.log('obj的类型是',typeof obj); </script>
从上面的例子可看出typeof的缺陷所在:不能检测出Array和普通对象,而会把它们都检测为Object;
【吐槽】:正所谓学而不思则罔,就在复习这个知识点的时候,我发现了一个极其有趣的现象!:null检测的类型是object!!是object!!!!
我还在知乎上找到了这样一段答案:
思路2:[变量 instanceof 类型] 能分别检测出array,普通object和function
<script type="text/javascript"> var fuc = function(){}, array = [1,2,3],obj ={}; console.log('fuc的类型是Function',fuc instanceof Function); console.log('array的类型是Array',array instanceof Array); console.log('obj的类型是Object',obj instanceof Object); console.log('fuc的类型是Object',fuc instanceof Object); console.log('array的类型是Object',array instanceof Object); </script>
对PHP:
思路1:gettype(变量) 能区分出任意数据类型
<?php class class_test{}; $obj = new class_test(); $array_test = [1,2,3]; $string_test = '字符串'; $int_test = 1; $float_test = 1.2; var_dump(gettype($obj));//检测对象 echo "<br/>"; var_dump(gettype($array_test));//检测数组 echo "<br/>"; var_dump(gettype($string_test));//检测字符串 echo "<br/>"; var_dump(gettype($int_test));//检测数组 echo "<br/>"; var_dump(gettype($float_test));//检测字符串 ?>
思路2:is_array()、is_bool()、is_float()、is_integer()、is_null()、is_numeric()、is_object()能检测任意数据类型
<?php class class_test{}; $obj = new class_test(); $array_test = [1,2,3]; $string_test = '字符串'; $int_test = 1; $float_test = 1.2; var_dump(is_object($obj));//检测对象 echo "<br/>"; var_dump(is_array($array_test));//检测数组 echo "<br/>"; var_dump(is_string($string_test));//检测字符串 echo "<br/>"; var_dump(is_integer($int_test));//检测数组 echo "<br/>"; var_dump(is_float($float_test));//检测字符串 echo "<br/>"; var_dump(is_numeric("12"));//检测是否为数字字符串或数字 echo "<br/>"; ?>
8.论打印变量的方式:
JS:console.log()打印基本类型的值,遇到对象或数组则打印对象属性或数组元素
PHP:一般有几种选择方式:
1.echo(注意这TM可能是个坑):只能打印标量:数字,字符串或布尔值,打印object或Array会报错,而且打印布尔值的时候true打印1,false时候什么也不打印
2.var_dump打印更详细变量的类型和值,它在打印object或者array的时候,会连数组元素的类型和值也打印出来(更暖更贴心)
• echo:
让我们来看看为什么我说它是个坑:
打印Array时报类型转换的警告,但仍能打印类型:
<?php $array = [1,2,3]; echo $array; ?>
打印object直接报错,连类型也不打印:
<?php class person{}; $obj = new person(); echo $obj; ?>
打印布尔值的时候若为true则打印1,若为false啥也不打印
<?php $true_value = true; $false_value =false; echo $true_value; echo "<br/>"; echo $false_value; ?>
var_dump相比起来就良心多了:
<?php class class_test{ var $value = '我是变量'; public function fuc(){ echo '我是方法'; } } $obj = new class_test(); $array_test = [1,2,3]; $string_test = '字符串'; $int_test = 1; $float_test = 1.2; var_dump($obj);//检测对象 echo "<br/>"; var_dump($array_test);//检测数组 echo "<br/>"; var_dump($string_test);//检测字符串 echo "<br/>"; var_dump($int_test);//检测整型 echo "<br/>"; var_dump($float_test);//检测浮点型 echo "<br/>"; ?>
业界良心有没有!
9.与JS相比,PHP没有作用域链的概念。
和JS一样,PHP也把作用域划分为函数作用域和全局作用域。但是由于PHP没有作用域链,所以函数作用域中不能访问全局作用域中的变量
JS:函数作用域能访问全局作用域中的变量,全局作用域不能访问函数作用域中的变量:
1函数作用域(最外层)能访问全局作用域中的变量
<script type="text/javascript"> var global_variable = '全局变量' ; function fuc(){ console.log(global_variable); } fuc(); </script>
运行结果:
2全局作用域不能访问函数作用域中的变量:
<script type="text/javascript"> function fuc(){ var area_variable = '局部变量' } fuc(); console.log(area_variable); </script>
运行:
PHP:函数作用域(最外层)不能访问全局作用域中的变量,全局作用域也不能访问函数作用域中的变量
函数作用域不能访问全局作用域中的变量【友情提示:各位JSer不要因为写了太多JS就以为所有的语言都有作用域链哦~】
<?php //在这里我们试图在函数作用域内访问全局作用域的变量 $variable = '变量'; function fuc (){ echo $variable; } fuc(); ?>
全局作用域也不能访问函数作用域中的变量(这是当然的啦):
<?php //在这里我们试图在全局作用域内访问函数作用域的变量 function fuc (){ $variable = '函数作用域中变量'; } fuc(); echo $variable; ?>
所以,PHP中两个作用域间的访问只能通过函数参数这一个“接口”
【一张图总结以上内容】
10.使用函数参数时,为引用传递还是值传递?
JS:只有值传递,没有引用传递(注意是只有值传递)
对于基本类型只有值传递
<script type="text/javascript"> function addNum(value){ return value = value +1; } var my_value = 1; addNum(my_value); console.log(my_value); </script>
输出为1而不是2,这说明,在运行函数fuc时候,仅仅是把my_value的值拷贝给一个新创建的局部变量value而已,然后对这个新变量进行操作,而不是针对原来定义的value变量
对于引用类型也只有值传递!【这点极易混淆!】:
在上面的例子中,可能容易让我们形成一种错误的概念,即值传递 == 对传入变量不会有影响,那是不是这样呢?
<script type="text/javascript"> function change_obj_name(obj){ obj.name = '不是彭湖湾' } var my_obj = {name:'彭湖湾'}; change_obj_name(my_obj); console.log(my_obj.name); </script>
运行结果:
可能有人会想:怎么调用函数时对象的名称被修改了?!!不是说好了JS是值传递吗?
对!JS是值传递,但在这里,传递的参数并不是对象,而是对象的地址(或引用)!!也就是说虽然存储my_obj对象地址的变量把值传递给了函数中创建的局部变量obj(值传递),但这两者仍然指向堆内存中的同一个对象,所以上述例子中对象的值才被修改了。
PHP:既有值传递,也有引用传递(定义函数时,function fuc($value){}是值传递,function fuc(&$value){}是引用传递)
先说说值传递:
<?php function add_num($value){ $value = $value + 1; } $num = 1; echo $num.' 是修改前的num'; add_num($num); echo "<br/>"; echo $num.' 是修改后的num'; ?>
再说说PHP引用传递:(习惯C语言的同学应该很熟悉吧,其实就在参数前加个&而已啦。。。)
<?php function add_num(&$value){ $value = $value + 1; } $num = 1; echo $num.' 是修改前的num'; add_num($num); echo "<br/>"; echo $num.' 是修改后的num'; ?>
11.比较数组相等时,对待==运算符和===运算符截然不同的表现
先上结论:
对JS,数组==数组(或===)比较的是两个数组的地址,而对PHP,数组==数组(或===)比较的是两个数组的“内容”
• js
<script type="text/javascript"> var array1 =[1,2,3]; var array2 =[1,2,3]; console.log('两个数组是否相等?',array1 == array2); console.log('两个数组是否恒等?',array1 == array2); </script>
即使“内容”相等,两个数组也不相等,这说明对JS,数组==数组(或===)比较的是两个数组的地址
• php:
<?php $array1 = [1,2,3]; $array2 = [1,2,3]; var_dump($array1 == $array2); ?>
【吐槽】:作为一名写JS的刚写到这里不禁说了句“卧槽!居然相等!”;
当然,作为一名写JS的,你很容易理解在PHP中数组==数组和数组===数组的区别,
对数组==数组:各个数组项对应的值相等,类型可以不同,例如“12”和12是相等的
对数组===数组,各个数组项对应的相等,类型也相同,“12”和12不相等!
<?php $array1 = [1,2,3]; $array2 = [1,'2',3]; echo "数组相等 "; var_dump($array1 == $array2); echo "数组恒等"; var_dump($array1 === $array2); ?>
我叫彭湖湾,请叫我胖湾