JavaScript 函數(shù)語(yǔ)法詳解
一、普通函數(shù)
js的函數(shù)創(chuàng)建比較特殊,有很多種方式,最簡(jiǎn)單的一種和c語(yǔ)言類(lèi)似。
特點(diǎn):
函數(shù)名字可以除了字母、數(shù)字、下劃線(xiàn)外,還可以存在 “$” 字符。
在js中,函數(shù)名就是一個(gè)儲(chǔ)存函數(shù)對(duì)象的變量。使用 typeof 關(guān)鍵字可以查看函數(shù)類(lèi)型。(這個(gè)理念和python類(lèi)似,可以用其他變量接手這個(gè)函數(shù))
函數(shù)形參定義時(shí)不需要寫(xiě)關(guān)鍵字:var、let、const。應(yīng)該默認(rèn)就是局部可修改變量。
JS 語(yǔ)法中 不檢查輸入?yún)?shù)。這意味著,輸入?yún)?shù)可少可多。少了輸入undefined代替,多了自動(dòng)忽略。
同上理,JS 也不拘束是否有返回值,統(tǒng)一都有返回值。如果沒(méi)有寫(xiě)明返回值,則統(tǒng)一返回?zé)o效值。
// 1. Function Definition
function printHello_1$_(name_0)
{
// execution
console.log("Hello World!" + name_0);
}
console.log(typeof printHello_1$_);
// 2. Function Invocation
printHello_1$_();
// 3. Function Naming
// 4. Function Parameters
// 5. Function Return
js還支持匿名函數(shù),就是不寫(xiě)函數(shù)名。python中也有類(lèi)似,在python學(xué)習(xí)筆記中也有記錄:lambda匿名函數(shù)。
// 6. 函數(shù)還可以沒(méi)名字,直接這樣創(chuàng)建。
let him = function(){
console.log("him");
}
him() // 側(cè)面反映了,名字其實(shí)就是一個(gè)變量名。
// 8. 函數(shù)名字本身不支持傳遞賦值,但是變量可以。
// him = printHello_1(); // 報(bào)錯(cuò)(有點(diǎn)類(lèi)似數(shù)組定義后就不能再賦值?)
let add = him;
add();
// 7. 該變量還是可以賦值其他內(nèi)容。
him = 6;
console.log(him) // 輸出數(shù)字 6
二、箭頭函數(shù)
js中箭頭函數(shù)就是“名副其實(shí)”的匿名函數(shù)了,可快速創(chuàng)建嵌套函數(shù)功能體(自創(chuàng)用詞)……也更加貼合python的lambda匿名函數(shù)用法。
在看實(shí)戰(zhàn)案例時(shí)全是這種匿名函數(shù)的創(chuàng)建和傳參,第一次接觸懵逼得不要不要的。下面的代碼為了方便看效果,我會(huì)把用不到的部分改成假,屏蔽運(yùn)行。你問(wèn)為什么不直接注釋?zhuān)恳驗(yàn)橄脲憻捰梅ā?/p>
使用方法看似簡(jiǎn)單,前面括號(hào)就是用到的參數(shù),箭頭后面緊跟代碼。如果是單行的簡(jiǎn)易代碼可不用寫(xiě)括號(hào),單行還自帶隱式返回計(jì)算值。
if (false)
{
const add = (a, b) => a + b; // 類(lèi)似直接創(chuàng)建函數(shù),并且將該函數(shù)丟給一個(gè)變量調(diào)用。
console.log(add(1,3)); // 沒(méi)有寫(xiě)返回值,還隱式返回了計(jì)算值
}
if (false)
{
let add = (a, b) => a + b;
console.log(add(1,3)); // 打印 4
const add_0 = add; // 可以正常的變量賦值替換
add = 5; // 可以看出本質(zhì)還是變量,如果定義是使用可變類(lèi)型,則可以改變
console.log(add); // 打印 5
console.log(add_0(2, 4)); // 打印 6
}
if (false)
{
console.log(add_0(10, 4)); // const 變量類(lèi)型不可以跨作用域
}
如果是需要換行,就需要用大括弧。常用。
if (false)
{
const add = (a, b) =>
{
return a + b;
}
console.log(add(1,3)); // 有返回值,表示如果用了大括號(hào)可以表示換行但是不會(huì)有隱式返回。而單行總是會(huì)有隱式返回的。
}
三·、數(shù)據(jù)包 JSON
JSON(JavaScript Object Notation, JS 對(duì)象簡(jiǎn)譜) 是一種輕量級(jí)的數(shù)據(jù)交換格式。它基于 ECMAScript (歐洲計(jì)算機(jī)協(xié)會(huì)制定的js規(guī)范)的一個(gè)子集,采用完全獨(dú)立于編程語(yǔ)言的文本格式來(lái)存儲(chǔ)和表示數(shù)據(jù)。簡(jiǎn)潔和清晰的層次結(jié)構(gòu)使得 JSON 成為理想的數(shù)據(jù)交換語(yǔ)言。 易于人閱讀和編寫(xiě),同時(shí)也易于機(jī)器解析和生成,并有效地提升網(wǎng)絡(luò)傳輸效率?!窘刂涟倏啤?/p>
- 在之前學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)和ros時(shí)也有接觸這類(lèi)數(shù)據(jù)包,一個(gè)小小的后綴.json文件,裝著一堆參數(shù)或數(shù)據(jù)集。從格式上看,很像字典,有鍵和值成對(duì)。如果展開(kāi)圖形化,其實(shí)是一個(gè)列表,有表頭和數(shù)據(jù)。
- js提供Object類(lèi)來(lái)創(chuàng)建json對(duì)象。(其實(shí)就是創(chuàng)建對(duì)象,下一節(jié)再細(xì)說(shuō))
// 例子1
if (false)
{
const book = new Object({title : "1984", author : "George Orwell"}) // 創(chuàng)建 JSON 對(duì)象
console.log("\n ---------")
console.log(typeof book) // 查看類(lèi)型,確實(shí)是對(duì)象
console.log(book) // 能正常打印
}
// 例子2(下一節(jié)細(xì)說(shuō),對(duì)象的知識(shí)點(diǎn))
if (false)
{
const book = ({title : "1984", author : "George Orwell"}) // 就算不加關(guān)鍵詞 Object 也能有相同效果。
console.log("\n ---------")
console.log(typeof book)
console.log(book)
}
// 例子3
if (false)
{
const book = [
{title : "1984", author : "George Orwella"},
{title : "1985", author : "George Orwellb"},
{title : "1986", author : "George Orwellc"},
{title : "1987", author : "George Orwelld"}
]
console.log("\n ---------")
console.log(typeof book) // 打印類(lèi)型還是對(duì)象 object,但是實(shí)際上一個(gè)算是數(shù)組
console.log(book)
}
- js提供將json對(duì)象數(shù)據(jù)轉(zhuǎn)換為字符串的方法:
JSON.stringify()。
if (false)
{
const book = ({title : "1984", author : "George Orwell"}) // 就算不加關(guān)鍵詞 Object 也能有相同效果。
console.log("\n ---------")
let bookJSON = JSON.stringify(book); // 將對(duì)象保留原本格式,轉(zhuǎn)換為了字符串,其中鍵名變成了字符串(就是加了雙引號(hào))?方便用于保存在文本內(nèi)?
console.log(typeof bookJSON) // 想起來(lái),JSON不也是之前我寫(xiě)ros工程時(shí)用到的參數(shù)文件嗎,還有百度飛漿的文本文件都是這種格式。
console.log(bookJSON)
}
/* 輸出內(nèi)容如下:
---------
string
{"title":"1984","author":"George Orwell"}
*/
// 可以發(fā)現(xiàn)鍵值還是原本的字符串,但是鍵名已經(jīng)變換為字符串
我做了一個(gè)類(lèi)比實(shí)驗(yàn),看如下注釋。
if (false)
{
const book = ([1,23,3,"156"])
console.log("\n ---------")
console.log(typeof book) // 類(lèi)型依舊屬于 object
let bookJSON = JSON.stringify(book); // 依舊可以調(diào)用,不會(huì)出現(xiàn)報(bào)錯(cuò)。
console.log(typeof bookJSON) // 得到的結(jié)果 和原結(jié)果一模一樣的字符串。
console.log(bookJSON)
}
/* 輸出內(nèi)容如下:
---------
object
string
[1,23,3,"156"]
*/
// 可以發(fā)現(xiàn)函數(shù)好像沒(méi)有起到作用。判斷格式不符合json要求時(shí)不會(huì)起作用,也不會(huì)報(bào)錯(cuò)。
js提供將字符串?dāng)?shù)據(jù)轉(zhuǎn)換為json對(duì)象的方法:JSON.parse()。就是JSON.stringify()的逆操作了。
if (false)
{
let data_0 = "[1,2,3]";
let data = "{\"title\" : \"1984\", \"author\" : \"George Orwell\"}"; // 注意,JSON的字符串形式下,鍵和值都是要加雙引號(hào)的,弄成類(lèi)似字符串的形式。有一點(diǎn)不對(duì)都會(huì)轉(zhuǎn)換失敗。
let parsed = JSON.parse(data); // 逆向操作,將字符串再變回成對(duì)象類(lèi)型。會(huì)解析是否符合格式。
console.log("\n -----")
console.log(parsed); //
console.log(typeof parsed)
console.log(typeof data)
}
/* 輸出內(nèi)容如下:
-----
{ title: '1984', author: 'George Orwell' }
object
string
*/
// 需要注意的就是字符串中的斜桿表示比較麻煩
- 學(xué)習(xí)JSON格式數(shù)據(jù)的使用非常重要,json變量其實(shí)并非普通的數(shù)據(jù),而是包含眾多數(shù)據(jù)處理函數(shù)的對(duì)象。比如上述2個(gè)字符串和數(shù)據(jù)之間相互轉(zhuǎn)換的函數(shù),檢查在實(shí)戰(zhàn)中用到。分別是讀取數(shù)據(jù)和存儲(chǔ)數(shù)據(jù)的2個(gè)操作。
四、對(duì)象Object
js中的對(duì)象創(chuàng)建不同于python的類(lèi),而是直接創(chuàng)建對(duì)象。我直接看例子,結(jié)合例子展開(kāi)。
if (false)
{
let data_0 = "[1,2,3]";
let data = "{\"title\" : \"1984\", \"author\" : \"George Orwell\"}"; // 注意,JSON的字符串形式下,鍵和值都是要加雙引號(hào)的,弄成類(lèi)似字符串的形式。有一點(diǎn)不對(duì)都會(huì)轉(zhuǎn)換失敗。
let parsed = JSON.parse(data); // 逆向操作,將字符串再變回成對(duì)象類(lèi)型。會(huì)解析是否符合格式。
console.log("\n -----")
console.log(parsed); //
console.log(typeof parsed)
console.log(typeof data)
}
/* 輸出內(nèi)容如下:
-----
{ title: '1984', author: 'George Orwell' }
object
string
*/
// 需要注意的就是字符串中的斜桿表示比較麻煩
從格式可以看出,感覺(jué)是一堆屬性,有字符串,有匿名函數(shù)。而且不是用等于號(hào)而是用冒號(hào)賦值,就像字典的鍵對(duì)一樣。
所以現(xiàn)在看來(lái),其實(shí)json數(shù)據(jù)包,在js中相當(dāng)于對(duì)象的存在。如果是直接打印函數(shù)方法,會(huì)輸出類(lèi)似字符:[Function (anonymous)]。
除了一開(kāi)始直接賦值,也可以采用先創(chuàng)建空對(duì)象,再逐步添加值。如果已經(jīng)存在的屬性會(huì)覆蓋,否則就當(dāng)作是添加。(很簡(jiǎn)單粗暴)
// 2. 另一種創(chuàng)建對(duì)象的方法,使用構(gòu)造函數(shù)創(chuàng)建
if (false)
{
const book = new Object();
console.log(book); // 一開(kāi)始創(chuàng)建是空的
console.log(typeof book); //類(lèi)型是 object
book.title = "1984";
book.author = "George Orwell";
book.isAvailable = false; // 添加屬性
book.checkIn = function(){
this.isAvailable = true; // 添加方法
};
book.checkOut = function(){
this.isAvailable = false;
};
console.log(book); // 打印正常
console.log(typeof book);
// 3. 訪(fǎng)問(wèn)對(duì)象內(nèi)元素的方法:
console.log(book.title); // 類(lèi)似結(jié)構(gòu)體的訪(fǎng)問(wèn)
console.log(book["title"]); // 類(lèi)似字典的訪(fǎng)問(wèn),輸出結(jié)果是一樣的,注意,這樣訪(fǎng)問(wèn)的話(huà),鍵名一定要加雙引號(hào),看作字符串形式
console.log(book.checkIn); // 如果是訪(fǎng)問(wèn)函數(shù),如果不加括號(hào),會(huì)返回對(duì)象。打印類(lèi)似字符:[Function (anonymous)]
console.log(book.checkIn()); // 如果加括號(hào)就相當(dāng)于調(diào)用執(zhí)行.(返回值空,因?yàn)楹瘮?shù)內(nèi)沒(méi)用寫(xiě)返回值)
console.log(book["checkIn"]); // 也可以使用字典的形式訪(fǎng)問(wèn),結(jié)果一樣
console.log(book["checkIn"]()); // 就是這個(gè)括號(hào)是在方括號(hào)外面的。
}
- 上下文機(jī)制: this ,并不完全是在對(duì)象內(nèi)值指對(duì)象的名字,而是指代上下文使用的變量?(具體看視頻講解,我理解還不太透徹)
- 類(lèi)似于我使用的主體,我使用的主體是對(duì)象,返回的就是對(duì)象,我使用的函數(shù),返回的就是函數(shù)。所以this還可以在函數(shù)中使用,雖然函數(shù)本身也是一個(gè)對(duì)象(?)。
if (false)
{
const bookObj = { // 創(chuàng)建一個(gè)對(duì)象
checkIn : function(){ // 添加一個(gè)屬性
return this; // 這個(gè)屬性是一個(gè)方法,且有返回值,返回對(duì)象本身
}
}
function anotherCheckIn(){ // 創(chuàng)建一個(gè)函數(shù)
return this; // 返回一個(gè)函數(shù)本身
}
console.log(bookObj.checkIn() == bookObj); // 返回值是不是對(duì)象本身,對(duì)的
console.log(bookObj.checkIn() == globalThis); // 返回值是不是函數(shù),錯(cuò)的
console.log(anotherCheckIn() == globalThis); // 返回值是不是函數(shù),對(duì)的
}
五、Promise
懵逼的一節(jié),講js中的異步運(yùn)行機(jī)制?不多解釋?zhuān)略秸f(shuō)越錯(cuò)。
// Promise 對(duì)象用于表示一個(gè)異步操作的最終完成 (或失敗)及其結(jié)果值。
if (true)
{
function promiseTimeout(ms){ // 創(chuàng)建一個(gè)函數(shù)
return new Promise((resolve, reject) => { // 返回一個(gè) Promise 對(duì)象, 輸入?yún)?shù)是一個(gè)匿名函數(shù),其中匿名函數(shù)又有2個(gè)參數(shù),一個(gè)是成功時(shí)會(huì)執(zhí)行的內(nèi)容,一個(gè)是失敗時(shí)會(huì)執(zhí)行的內(nèi)容
setTimeout(resolve, ms); // js內(nèi)部函數(shù),延時(shí)第二個(gè)參數(shù)ms后執(zhí)行 第一個(gè)參數(shù)的內(nèi)容。
});
}
promiseTimeout(2000) // 調(diào)用函數(shù),傳入?yún)?shù)2000ms;
.then(() => { // 返回的 Promise 對(duì)象的內(nèi)置方法;如果成功則會(huì)調(diào)用。該內(nèi)置方法也有一個(gè)參數(shù),該參數(shù)是匿名函數(shù)
console.log('Done!!'); // 該匿名函數(shù)無(wú)參入?yún)?shù),內(nèi)部功能只有打印
return promiseTimeout(1000); // 再調(diào)用一次函數(shù),又返回一個(gè)變量
}).then(() => { // 因?yàn)樯厦嬗址祷亓艘粋€(gè)變量,所以可以鏈?zhǔn)秸{(diào)用,
console.log('Also done!!'); // 延時(shí)1000ms,運(yùn)行成功后會(huì)接著調(diào)用
return Promise.resolve(42); // 又返回一個(gè)對(duì)象,無(wú)限套娃
}).then((result_0) => { // 傳入?yún)?shù),這個(gè)參數(shù)名字是隨意的,我修改后還是能實(shí)現(xiàn)效果。ide自動(dòng)標(biāo)紅,應(yīng)該能知道是變量,而非語(yǔ)法關(guān)鍵字
console.log(result_0); // 打印參數(shù)
})
.catch(() => { // 同上,不過(guò)是失敗時(shí)調(diào)用
console.log('Error!');
})
// 因?yàn)?Promise.prototype.then 和 Promise.prototype.catch 方法返回的是 promise, 所以它們可以被鏈?zhǔn)秸{(diào)用。
}
/*
運(yùn)行結(jié)果為:
先稍等一會(huì)打印一行:
Done!
稍等片刻后再同時(shí)先后打印兩行:
Also done!
42
*/
六、Async : Await
和Promise機(jī)制相反。
// Async:Await
function promiseTimeout(ms){
return new Promise((resolve, reject) => {
setTimeout(resolve, ms);
});
}
async function longRunningOperation(){
return 42;
}
async function run(){
console.log('Start!');
await promiseTimeout(2000); // 添加await關(guān)鍵字,結(jié)果類(lèi)似去同步運(yùn)行。本來(lái)使用Promise會(huì)使先打印,后延時(shí),如果加上A/A后就會(huì)按順序先延時(shí)再打印。
const response = await longRunningOperation();
console.log(response); // 按道理應(yīng)該直接返回42并打印,實(shí)際上,如果不加await關(guān)鍵字,會(huì)立刻返回一個(gè)Promise對(duì)象,而不是42.
console.log('Stop!!');
}
run();
/*
運(yùn)行結(jié)果為:
先打印一行:
Start!
稍等片刻后再同時(shí)先后打印兩行:
42
Stop!
*/
七、包
使用node.js中附帶的nvm工具,可以很好的管理js軟件包。而且工程可以配備了相關(guān)軟件包目錄。只需要在其中添加對(duì)應(yīng)軟件包,再輸入更新工程指令就可以在工程中添加軟件包。
類(lèi)似于編譯一樣,不過(guò)這個(gè)是下載。過(guò)去python提倡將軟件包直接安裝在電腦工作環(huán)境空間內(nèi)。而c語(yǔ)言的相關(guān)庫(kù)是建議在工程內(nèi)。js也是提倡在工程內(nèi)。不過(guò)如果要轉(zhuǎn)移程序時(shí),會(huì)講軟件包文件夾刪除。只轉(zhuǎn)移工程代碼部分。轉(zhuǎn)移完畢后在別的電腦上再使用更新下載功能即可。這個(gè)操作有點(diǎn)像之前學(xué)過(guò)的ros工程。不過(guò)ros工程就算不設(shè)置正確也能正常運(yùn)行,js如果設(shè)置不準(zhǔn)確,在編譯時(shí)就不通過(guò)了。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
JavaScript運(yùn)行機(jī)制之事件循環(huán)(Event Loop)詳解
這篇文章主要介紹了JavaScript運(yùn)行機(jī)制之事件循環(huán)(Event Loop)詳解,本文從多個(gè)方面講解了Event Loop,需要的朋友可以參考下2014-10-10
你應(yīng)該了解的JavaScript Array.map()五種用途小結(jié)
大家都知道m(xù)ap() 方法返回一個(gè)新數(shù)組,數(shù)組中的元素為原始數(shù)組元素調(diào)用函數(shù)處理后的值。下面這篇文章主要給大家介紹了關(guān)于JavaScript Array.map()的五種用途,需要的朋友可以參考下2018-11-11
解決canvas畫(huà)布使用fillRect()時(shí)高度出現(xiàn)雙倍效果的問(wèn)題
下面小編就為大家?guī)?lái)一篇解決canvas畫(huà)布使用fillRect()時(shí)高度出現(xiàn)雙倍效果的問(wèn)題。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08
JS控制網(wǎng)頁(yè)動(dòng)態(tài)生成任意行列數(shù)表格的方法
這篇文章主要介紹了JS控制網(wǎng)頁(yè)動(dòng)態(tài)生成任意行列數(shù)表格的方法,實(shí)例分析了javascript操作表格節(jié)點(diǎn)控制dom元素添加的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03
JavaScript純前端實(shí)現(xiàn)在線(xiàn)GIF壓縮
這篇文章主要為大家詳細(xì)介紹了如何利用JavaScript純前端實(shí)現(xiàn)在線(xiàn)GIF壓縮工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03
js編寫(xiě)三級(jí)聯(lián)動(dòng)簡(jiǎn)單案例
這篇文章主要為大家分享了JavaScript編寫(xiě)三級(jí)聯(lián)動(dòng)簡(jiǎn)單案例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12
容易造成JavaScript內(nèi)存泄露幾個(gè)方面
這篇文章主要介紹了容易造成JavaScript內(nèi)存泄露幾個(gè)方面,本文講解了多個(gè)會(huì)在Chrome V8中產(chǎn)生內(nèi)存泄漏的示例,需要的朋友可以參考下2014-09-09
詳解微信小程序「渲染層網(wǎng)絡(luò)層錯(cuò)誤」的解決方法
這篇文章主要介紹了詳解微信小程序「渲染層網(wǎng)絡(luò)層錯(cuò)誤」的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01

