NodeJs基本語法和類型
寫在前面
今天想要查下Node的類型什么的知識,想要總結(jié)下,在Googol上看到一個文章,但是原始的鏈接不在了,在快照中把這篇文章拉出來,如果原作者有問題,請聯(lián)系我!
該文章都是一些JS的基礎(chǔ),高手自動跳過!我之前沒怎么寫過js,這方面比較弱,所以在寫node的時候也遇到了麻煩,這里給自己補充下知識!
正文
Node.js 的基礎(chǔ)是 JavaScript 這門 腳本語言。而大多數(shù)的腳本語言一個共同的特點就是“弱類型”。
不同于 PHP 的是,PHP 就是是有了新變量也無需申明,而 JavaScript 則還是需要 var 來申明一下的。而這個 var 涵蓋了 C++ 中的int、string、char等一切類型的含義,甚至是 function。
本篇以及后篇的所有內(nèi)容都是在 Linux 或者 Cygwin 下用 vim 進行編輯(若不是則請自行轉(zhuǎn)變成你自己的方法),然后在命令行下進行查看結(jié)果的。
基本語法
變量聲明
在 C/C++ 中,我們這么聲明變量的:
```C++
void foo() {}
int a = 0;
char b = 'a';
float c = 1.0f;
void (*d)() = foo; ///< 忘了是不是這么寫的了,總之是函數(shù)指針
而在 Node.js 中則是這樣的:
```javascript
function foo() {}
var a = 0;
var b = 'a';
var c = 1.0;
var d = foo;
所以,無論是什么類型的變量,在 Node.js 中都是以一個 var 來解決的。
循環(huán)語句
for…i
這個循環(huán)語句基本上跟 C/C++ 一樣,都是
```C++
for(int i = 0; i < foo; i++)
{
//...
}
而鑒于 Node.js 是弱類型,所以只需要:
```javascript
for(var i = 0; i < foo; i++) {
//...
}
for…in
這是一種后有型的循環(huán)語句,類似于 PHP 的 foreach。
比如我們有一個 JSON對象 如下:
javascript
var foo = {
"hello" : "world",
"node" : "js",
"blahblah" : "bar"
};
這個時候我們就可以用 for...in 來循環(huán)遍歷了:
javascript
for(var key in foo) {
console.log(key + ": " + foo[key]);
}
我們?nèi)绻诿钚兄写蛉胂旅娴拿睿?/p>
$ node foo.js
屏幕上就會顯示下面的內(nèi)容了:
hello
: world
node: js
blahblah: bar
提示:由上可知,for...in 語句是用來遍歷 JSON對象、數(shù)組、對象的鍵名的,而不提供鍵值的遍歷。如果要獲取鍵值,只能通過foo[<當(dāng)前鍵名>]的形式來獲取。這個跟 PHP 的 foreach 還是有一定區(qū)別的。
while…do, do…whill
這個就不多做解釋了,跟其它語言沒什么大的區(qū)別,無非就是如果有變量聲明的話,需要用 var 就夠了。
運算符
+, -, *, /
這幾個運算符也就這樣,要注意的是 +。它既可以作用于字符串,也可以作用于數(shù)值運算。弱類型語言雖然說類型是弱的,數(shù)字有時候可以以字符串的形態(tài)出現(xiàn),字符串有時候可以用數(shù)值的形態(tài)出現(xiàn),但是在必要的時候也還是要說一下它是什么類型的,我們可以用下面的代碼去看看結(jié)果:
var a = "1";
var b = 2;
console.log(a + b);
console.log(parseInt(a) + b);
這里的 parseInt 是 Node.js 的一個內(nèi)置函數(shù),作用是將一個字符串解析成 int 類型的變量。
上面的代碼執(zhí)行結(jié)果是:
12
3
注:第一個 console.log 結(jié)果是 12,由于 a 是字符串,所以 b 也被系統(tǒng)以字符串的姿態(tài)進行加操作,結(jié)果就是將兩個字符串黏連在一起就變成了 12。而第二個 console.log 結(jié)果是 3,是因為我們將第一個 a 轉(zhuǎn)變?yōu)榱?int 類型,兩個 int 型的變量相加即數(shù)值相加,結(jié)果當(dāng)然就是 3 了。
==, ===, !=, !==
這里有一點要解釋,當(dāng)這個邏輯運算符長度為 2 的時候(==, !=),只是判斷外在的值是不是一樣的,而不會判斷類型。如
var a = 1, b = "1";
console.log(a == b);
它輸出的結(jié)果就是 true 。但是如果我們在中間判斷的時候再加上一個等號,那么就是嚴格判斷了,需要類型和值都一樣的時候才會是 true,否則就是 false。也就是說
var a = 1, b = "1";
console.log(a === b);
的時候,返回的結(jié)果就是 false 了,因為 a 是 int 型的,而 b 則是字符串。
順帶著就把條件語句講了吧,其實這里的 if 跟別的語言沒什么兩樣,就是幾個邏輯運算符兩個等號三個等號的問題。所以就不多做累述了。
typeof
這里我姑且把它當(dāng)成是一個運算符而不是函數(shù)了。
這個運算符的作用是判斷一個變量的類型,會返回一個字符串,即類型名,具體的執(zhí)行下面的代碼就知道了:
function foo() {}
var a = 0;
var b = '噓~蛋花湯在睡覺。';
var c = 1.0;
var d = foo;
var e = { "a" : a };
var f = [ 1, 2, 3 ];
var g = null;
var h = undefined;
console.log(typeof a);
console.log(typeof b);
console.log(typeof c);
console.log(typeof d);
console.log(typeof e);
console.log(typeof f);
console.log(typeof g);
console.log(typeof h);
這里的執(zhí)行結(jié)果就將會是:
number
string
number
function
object
object
object
undefined
null, undefined, NaN
在 JavaScript 中,有三個特殊的值,如標(biāo)題所示。其中第一個大家可能都比較熟悉吧,C/C++ 里面也有,不過是大寫的,其本質(zhì)就是一個
```C++
define NULL 0
而在 JavaScript 中,這三個值所代表的意義都不同。
### null ###
null 是一種特殊的 object,大致的意思就是空。比如說:
var a = null;
大家都能看懂,就不多做解釋了。但是跟 C/C++ 不同的是,這個 null 跟 0 不相等。
### undefined ###
這個東西的意思就是說這個變量未聲明。為了能夠更好地區(qū)分 null,我們的樣例代碼如下寫:
```javascript
var a = {
"foo" : null
};
console.log(a["foo"]);
console.log(a["bar"]);
上面的代碼中,我們讓 a["foo"] 的值為空,即 null。而壓根沒有聲明 a["bar"] 這個東西,它連空都不是。輸出的結(jié)果大家都差不多應(yīng)該猜到了:
null
undefined
NaN
這是一個空的數(shù)值,是一個特殊的 number。它的全稱是 Not a Number。有點奇怪,大家可以理解為 不是數(shù)字形態(tài),或者數(shù)值出錯的 number 類型變量。
多在浮點型數(shù)值運算錯誤(如被0除)的情況下出現(xiàn),甚至可以是用戶自己讓一個變量等于 NaN 以便返回一個錯誤值讓大家知道這個函數(shù)運算出錯了云云。
小雜碎
其它剩余的語句也跟已存在的其它語言差不多,比如說 break 啊、switch 啊、continue 啊等等等等。
變量類型
這一節(jié)主要講的是 JavaScript 對象,其它類型差不多一帶而過吧。
基礎(chǔ)類型
Node.js 包含的基礎(chǔ)類型差不多有如下幾個:
number
string
boolean
array
其中前三種類型可以直接賦值, 而 array 的賦值只是一個引用賦值而已,在新變量中改變某個值的話舊變量的值也會改變 ,直接可以試試下面的代碼:
javascript
var foo = [ 1, 2, 3 ];
var bar = foo;
bar[0] = 3;
console.log(foo);
它得出的結(jié)果是:
javascript
[ 3, 2, 3 ]
也就是說 array 要是復(fù)制出一個新的數(shù)組的話,不能用直接賦值的方法,而必須“深拷貝”。
這里有必要講一下 array 的三種創(chuàng)建方法。
第一種:
javascript
var dog = new Array();
dog[0] = "噓~";
dog[1] = "蛋花湯";
dog[2] = "在睡覺";
第二種:
javascript
var dog = new Array( "噓~", "蛋花湯", "在睡覺" );
第四種:
javascript
var dog = [
"噓~",
"蛋花湯",
"在睡覺"
];
我個人比較喜歡第三種寫法,比較簡潔。
JSON對象
這里我把 JSON對象 單獨拎出來而不是把它歸類為 JavaScript對象,如果覺得我有點誤人子弟就可以直接跳過這一節(jié)了。
本人對于 JSON對象 和 JavaScript 對象的區(qū)分放在 是否只用來存儲數(shù)據(jù),而并非是一個類的實例化。其實 JSON 的本質(zhì)便是 JavaScript Object Notation。
更多有關(guān) JSON 的信息請自行百科。
在 Node.js 中聲明一個 JSON對象 非常簡單:
javascript
var dog = {
"pre" : "噓~",
"sub" : {
"name" : "蛋花湯",
"act" : "在睡覺",
"time" : 12
},
"suf" : [ "我說了", "它在睡覺", "就是在睡覺" ]
};
有兩種方式能得到 JSON對象 中的某個鍵名的鍵值,第一種是用點連接,第二種是用中括號:
javascript
dog
.pre;
dog["pre"];
注意:上面在用點的時候,后面直接跟的是JSON中的key,如果把key當(dāng)成是變量去當(dāng)問,只能用dog[key]試試看:現(xiàn)在你自己動手試試看,用 for...in 的形式遍歷一遍上面的 JSON對象。別忘了用上 typeof 喵~
類(對象)的基礎(chǔ)
嚴格意義上來講,Node.js 的類不能算是類,其實它只是一個函數(shù)的集合體,加一些成員變量。它的本質(zhì)其實是一個函數(shù)。
不過為了通俗地講,我們接下去以及以后都將其稱為“類”,實例化的叫“對象”。
因為類有著很多 函數(shù) 的特性,或者說它的本質(zhì)就是一個 函數(shù),所以這里面我們可能一不留神就順帶著把函數(shù)基礎(chǔ)給講了。
類的聲明和實例化
聲明一個類非常簡單,大家不要笑:
javascript
function foo() {
//...
}
好了,我們已經(jīng)寫好了一個 foo 類了。
真的假的?!真的。
不信?不信你可以接下去打一段代碼看看:
javascript
var bar = new foo();
別看它是一個函數(shù),如果以這樣的形式(new)寫出來,它就是這個類的實例化。
而這個所謂的 foo() 其實就是這個 foo() 類的構(gòu)造函數(shù)。
成員變量
成員變量有好兩種方法。
第一種就是在類的構(gòu)造函數(shù)或者任何構(gòu)造函數(shù)中使用 this.<變量名> 。你可以在任何時候聲明一個成員變量,在外部不影響使用,反正就算在還未聲明的時候使用它,也會有一個 undefined 來撐著。所以說這就是第一種方法:
javascript
function foo() {
this.hello = "world";
}
注意:只有在加了 this 的時候才是調(diào)用類的成員變量,否則只是函數(shù)內(nèi)的一個局部變量而已。要分清楚有沒有 this 的時候變量的作用范圍。
第二種方法就是在構(gòu)造函數(shù)或者任何成員函數(shù)外部聲明,其格式是 <類名>.prototype.<變量名>:
javascript
function foo() {
//...
}
foo.prototype.hello = "world";
無論上面哪種方法都是對成員變量的聲明,我們可以看看效果:
javascript
var bar = new foo();
console.log(bar.hello);
甚至你可以這么修改這個類:
javascript
function foo() {
this.hello = "world";
}
foo.prototype.hello = "蛋花湯";
然后再用上面的代碼輸出。
想想看為什么輸出的還是 world 而不是 蛋花湯。
構(gòu)造函數(shù)
我們之前說過了這個 foo() 實際上是一個 構(gòu)造函數(shù)。那么顯然我們可以給構(gòu)造函數(shù)傳參數(shù),所以就有了下面的代碼:
javascript
// 代碼2.1
function foo(hello) {
if(hello === undefined) {
this.hello = "world";
} else {
this.hello = hello;
}
}
我們看到上面有一個奇葩的判斷 if(hello === undefined),這個判斷有什么用呢?第一種可能,就是開發(fā)者很蛋疼地特意傳進去一個 undefined 進去,這個時候它是 undefined 無可厚非。
還有一種情況。我們一開始就說了 JavaScript 是一門弱類型語言,其實不僅僅是弱類型,它的傳參數(shù)也非常不嚴謹。你可以多傳或者少傳(只要保證你多傳或者少傳的時候可以保證程序不出錯,或者邏輯不出錯),原則上都是可以的。多傳的參數(shù)會被自動忽略,而少傳的參數(shù)會以 undefined 補足。
看看下面的代碼就明白了:
javascript
// 上接代碼2.1
var bar1 = new foo();
var bar2 = new foo("蛋花湯");
請自行輸出一下兩個 bar 的 hello 變量,會發(fā)現(xiàn)一個是 world 一個是 蛋花湯。顯而易見,我們的第一個 bar1 在聲明的時候,被 Node.js 自動看成了:
javascript
var bar1 = new foo(undefined);
所以就有了它是 world 一說。
還有就是在這個構(gòu)造函數(shù)中,我們看到了傳進去的參數(shù)是 hello 而這個類中本來就有個成員變量就是 this.hello。不過我們之前說過了有 this 和沒 this 的時候作用域不同,那個參數(shù)只是作用于構(gòu)造函數(shù)中,而加了 this 的那個則是成員變量。用一個 this 就馬上區(qū)分開來他們了,所以即使同名也沒關(guān)系。
成員函數(shù)
成員函數(shù)聲明
成員函數(shù)的聲明跟成員變量的第二種聲明方法差不多,即 <類名>.prototype.<函數(shù)名> = <函數(shù)>;
javascript
// 上接代碼2.1
function setHello(hello) {
this.hello = hello;
}
foo.prototype.setHello = setHello;
bar1.setHello("雞蛋餅");
上面這段代碼顯而易見,我們實現(xiàn)了 foo 類的 setHello 函數(shù),能通過它修改 foo.hello 的值。
但是這么寫是不是有點麻煩?接下去我要講一個 JavaScript 函數(shù)重要的特性了。
★ 匿名函數(shù) ★
很多時候我們的某些函數(shù)只在一個地方被引用或者調(diào)用,那么我們?yōu)檫@個函數(shù)起一個名字就太不值了,沒必要,所以我們可以臨時寫好這個函數(shù),直接讓引用它的人引用它,調(diào)用它的人調(diào)用它。所以函數(shù)可以省略函數(shù)名,如:
javascript
function(hello) {
this.hello = hello;
}
至于怎么引用或者調(diào)用呢?如果是上面的那個類需要引用的話,就是寫成這樣的:
javascript
foo.prototype.setHello = function(hello) {
this.hello = hello;
}
這樣的寫法跟 成員函數(shù) 聲明 是一個效果的,而且省了很多的代碼量。而且實際上,基本上的類成員函數(shù)的聲明都是采用這種匿名函數(shù)的方式來聲明的。
至于說怎么樣讓匿名函數(shù)被調(diào)用呢?這通常用于傳入一個只被某個函數(shù)調(diào)用的函數(shù)時這樣寫。
比如我們有一個函數(shù)的原型是:
javascript
/**
* 我們將傳入a,b兩個變量,
* 在算出a+b的值后,交由func(num)
* 去進行輸出
*/
function sumab(a, b, func) {
var c = a + b;
func(a, b, c);
}
比如我們有兩個版本的輸出函數(shù),一個是中文輸出,一個是英文輸出,那么如果不用匿名函數(shù)時候是這么寫的:
javascript
function zh(a, b, sum) {
console.log(a + " + " + b + " 的值是:" + sum);
}
function en(a, b, sum) {
console.log(a + " plus " + b + " is " + sum);
}
sumab(1, 2, zh);
sumab(3, 4, en);
執(zhí)行一遍這段代碼,輸出的結(jié)果將會是:
1 + 2 的值是:3
3 plus 4 is 7
這樣的代碼如果采用匿名函數(shù)的形式則將會是:
javascript
sumab(1, 2, function(a, b, sum) {
console.log(a + " + " + b + " 的值是:" + sum);
});
sumab(3, 4, function(a, b, sum) {
console.log(a + " plus " + b + " is " + sum);
});
這種形式通常使用于回調(diào)函數(shù)?;卣{(diào)機制算是 Node.js 或者說 JavaScript 的精髓。在以后的篇章會做介紹。
成員函數(shù)聲明的匿名函數(shù)聲明方式
雖然上一節(jié)講過了,不過還是再講一遍吧。
通常我們聲明類的成員函數(shù)時候都是用匿名函數(shù)來聲明的,因為反正那個函數(shù)也就是這個類的一個成員函數(shù)而已,不會在其它地方被單獨引用或者調(diào)用,所以就有了下面的代碼:
javascript
// 上接代碼2.1
foo.prototype.setHello = function(hello) {
this.hello = hello;
}
這樣我們就使得 foo 類有了 setHello 這個函數(shù)了。
2.3.4. 類的隨意性
這個又是我胡扯的。所謂類的隨意性即 JavaScript 中你可以在任何地方修改你的類,這跟 Ruby 有著一定的相似之處。
比如說 string ,它其實也是一個類,有著諸如 length 這樣的成員變量,也有 indexOf、substr 等成員函數(shù)。但是萬一我們覺得這個 string 有些地方不完善,想加自己的方法,那么可以在你想要的地方給它增加一個函數(shù),比如:
javascript
String.prototype.sb = function() {
var newstr = "";
for(var i = 0; i < this.length; i++) {
if(i % 2 === 0) newstr += "s";
else newstr += "b";
}
return newstr;
};
這個函數(shù)的意思就是填充一個字符串,使其變成 sb 的化身。
我們來測試一下:
var str = "噓~蛋花湯在睡覺。";
console.log(str.sb());
你將會得到這樣的結(jié)果:
sbsbsbsbs
你跟你的電腦說“噓~蛋花湯在睡覺?!?,你的電腦會罵你四次半傻逼。(趕快砸了它)
3. 附
3.1. 深拷貝
所謂深拷貝就是自己新建一個數(shù)組或者對象,把源數(shù)組或者對象中的基礎(chǔ)類型變量值一個個手動拷過去,而不是只把源數(shù)組或者對象的引用拿過來。所以這就涉及到了一個遞歸的調(diào)用什么的。
下面是我實現(xiàn)的一個深拷貝函數(shù),大家可以寫一個自己的然后加入到自己的 Node.js 知識庫中。
javascript
function cloneObject(src) {
var dest = {};
for(var key in src) {
if(typeof src === "object") dest[key] = cloneObject(src[key]);
else dest[key] = src[key];
}
return dest;
}
相關(guān)文章
Node.js Windows Binary二進制文件安裝方法
這篇文章主要介紹了Node.js Windows Binary二進制文件安裝,本文給大家介紹的非常詳細,具有一定的參考借鑒價值 ,需要的朋友可以參考下2019-05-05用nodejs實現(xiàn)json和jsonp服務(wù)的方法
本篇文章主要介紹了用nodejs實現(xiàn)json和jsonp服務(wù)的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-08-08node.js利用socket.io實現(xiàn)多人在線匹配聯(lián)機五子棋
這篇文章主要介紹了node.js利用socket.io實現(xiàn)多人在線匹配聯(lián)機五子棋的操作方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2018-05-05使用Node.js配合Nginx實現(xiàn)高負載網(wǎng)絡(luò)
這篇文章主要介紹了使用Node.js配合Nginx實現(xiàn)高負載網(wǎng)絡(luò),Node的異步加上Nginx的反向代理在性能上實在是給力!需要的朋友可以參考下2015-06-06nvm報錯Now?using?node?v版本號(64-bit)圖文解決方法
這篇文章主要給大家介紹了關(guān)于nvm報錯Now?using?node?v版本號(64-bit)的解決方法,文中將解決的辦法介紹的非常詳細,對遇到這個問題的朋友具有一定的參考借鑒價值,需要的朋友可以參考下2023-11-11