區別有:1、C語言是被編譯成機器語言,而JS是作為腳本被解釋器解釋執行;2、C語言需要程式設計師手動管理內存,而JS的內存是由解釋器來管理的;3、C語言透過呼叫系統API來實現多線程,而JS是單線程。
本教學操作環境:windows7系統、javascript1.8.5版、Dell G3電腦。
1、C語言主要是被編譯成機器語言,而JavaScript主要是作為腳本被解釋器解釋執行;
2、C語言需要程式設計師手動管理記憶體(主要指堆記憶體的申請與釋放),而JavaScript的記憶體是由解譯器來管理的;
3、JavaScript是動態型別語言,變數的資料型別在執行時仍可變更;
4.JavaScript中的函數都與其定義時可存取到的變數組成閉包;
5、「類別的繼承與多型」等物件導向的特性的支持,而JavaScript可以透過原型鍊和閉包等實現物件導向的繼承、多型與封裝,實作ECMAScript 2015以上版本的JavaScript更是在語法層面支援類別的定義;
6、C語言可以透過呼叫系統API來實現多線程,可以透過多線程來提高阻塞操作(主要是IO)時的CPU利用率,而JavaScript主要是單線程,JavaScript的可能阻塞的操作都由JavaScript運行時提供的非同步API來完成
對於有C基礎的同學來說,學js是相當簡單的,文法類似,這裡主要列一下兩者的異同,基本上記住了這些異同點,就可以上手使用js了。只要幾天,甚至一天的學習,就可以用js在QT呼叫百度地圖,繪製立體模型等好玩的功能。
QT開發過程中,常常要用到qss、qml、js,跟前端三件套很像(CSS/HTML/JS),這裡記錄JS的常見語法。
C語言中的函數指標的概念,在JS中也是適用的,只不過JS中的函數指標並不是編譯級的,而是解釋級的,在底層實作上有所不同,但用法相同。
0、【變數宣告】在C語言中的變數必須先聲明,後使用;而JS允許不聲明直接用,當然也支援先宣告後使用,先使用後宣告。
1、【賦值與賦引用】js中的變數賦值時,除了基本型別是拷貝賦值以外,"其他"都是賦引用(所謂"其他",其實都是JS中的物件變數)。 C語言的賦值,都是拷貝賦值,除非你明確地指定要賦引用。
2、【回呼】兩者都有回呼函數的概念,而且函數名就是回呼變數名,C和JS都是如此。
3、【自呼叫】。 JS可以在定義函數的時候,立即呼叫一次。語法為:
无参函数示例 (function fooA (){ //这里是函数体 })(); 有参函数示例: (function fooB(var a){ //这里是函数体 })(5);
就是把整個函數定義,用小括號A括住(這就相當於拿到了該函數的函數指標),然後後面再加一個括號B(這就等於執行這個函數),後面的小括號B,可以填參數。而且這裡的函數名可省略不寫。
4、【函數內定義函數】JS允許在函數內部繼續定義函數。
5、【閉包】
這個概念比較新鮮,在C/C 中沒見過,透過閱讀JS教學發現這東西也簡單的很,就是起的名字太唬人了,簡單來講,這種程式設計手法,可以讓某個函數擁有局部靜態變數。
一般來說,JS中變數的作用域,與C是一致的,函數內的變量,在函數外是無法存取的,除非你用函數的形參或傳回值,把局部變數的指針,要弄到外面,這樣函數外面的程式碼就可以用指針操作某個函數內部局部靜態變數了。與此類似,JS中也有這種手法,這種手法的名字叫做閉包。差別在於,C從函數中丟出的是某個局部靜態變數的指針,而JS丟出的是能夠操作這個局部變數的的函數的指針。
為了對比,先來一個C語言版本的「閉包」:
uint8_t *getBuf(void) { static uint8_t buf[1024]; return buf; } void sendCmd() { uint8_t *cmdBuf = getBuf(void); cmdBuf[0] = 0xA5; cmdBuf[1] = 0xFF; .... send(cmdBuf, 10); }
getBuf函數中有一個局部靜態數組buf,本來程式的其他程式碼是無法存取到它的,但是我們透過該函數的回傳值,將其首地址送出來,就實現了外部程式碼對該數組的存取。例如sendCmd函數就使用了一下這個陣列。
下面是JS版本:
場景(1):函數A內定義了變數a和函數B,顯然B是可以存取a的,如何才能讓A外面的程式碼存取到a呢?有2種思路,一種是回傳a的引用,另一種是閉包。回傳引用就不說了,因為a在A執行完後記憶體會被釋放,回傳a的引用也無法存取a。
var aRef = (function A(){ var a = 2; return function B(){ return a++; } })(); alert(aRef()); alert(aRef());
上述程式碼的效果為,彈出提示框,內容為數字2, 然後再次彈出提示框,內容為數字3。其中函數名A和函數名B均可不寫。
我们来分析一下上述代码,首先函数A是个自调用函数(也可以不自调用,后面有例子),所以A里面变量a立即被赋值为2,函数A的返回值为函数B的函数指针,所以变量aRef就是个函数指针,以后调用aRef( ),就相当于调用了函数B( )。而B( )的返回值为a++。按照JS的设计机制,这种情形下的变量a将会常驻内存,这就是实现了让函数A拥有局部静态变量,而这个局部静态变量,只能被A返回的函数指针(也即函数B)修改。
基于上述分析,我们可以把上述代码改成这样,更容易阅读:
var aRef = (function A(){ var a = 2; function B(){ return a++; } return B; })(); 也可以改成这样: function A(){ var a = 2; function B(){ return a++; } return B; } var aRef = A();//A没有进行自调用,只能在这里调一次,才能获取到B的函数指针
情形2:经典的JS定时器闭包。题目:使用for循环,每秒打印出for当前的值。
错误写法:
for(var i = 1; i <= 5; i++) { setTimeout(function(){ alert(i); }, 1000); }
执行的效果是,连续弹出5次数字5,而不是预想的依次弹出12345。原因是,第一次执行定时器的回调函数前,i的值就已经变成5了,后续4次定时回调,i的值也是5.
正确写法:
for(var i = 1; i <= 5; i++) { (function(a){ setTimeout(function(){alert(a);}, 1000); })(i); }
这里使用了一个匿名的自调用函数(为了叙述方便,我下面称之为out函数),在函数内部又声明了匿名的定时器回调函数(为了叙述方便,我下面称之为in函数),因此使得in函数成了闭包函数,从而使得out函数的局部变量a常驻内存了。
为了更清楚de看明白它的原理,我们再把这段代码改成这样,增强可读性:
function outFunc(a){ function inFunc(){ alert(a); } setTimeout(inFunc, 1000); } for(i = 0; i < 4; i++) { outFunc(i); }
这段代码看起来清晰了,可以一目了然地看出其中的闭包语法。
总结一下闭包就是:一旦执行了闭包函数所在的外部函数,那么这个外部函数所维护的局部变量,将会常驻内存。
最后来一个实例应用,看看闭包在实际场景中是如何应用的。题目:有如下C语言函数,请把它改成js版。
uint32_t readVol(void) { static uint8_t callCnt = 0; callCnt++; return callCnt; }
这个C函数的功能很简单,就是每次调用时,会返回该函数被调的次数,也即readVol这个函数拥有自己的局部静态变量。用js实现如下:
var readVol = (function () { var callCnt = 0; return function() { callCnt++; return callCnt; } })();
这个readVol函数与C语言的readVol函数功能完全一致。
【推荐学习:javascript高级教程】
以上是c和javascript差別有哪些的詳細內容。更多資訊請關注PHP中文網其他相關文章!