本文將從以下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); ?>