JavaScript 函式語法詳解
目錄
- 一、普通函式
- 二、箭頭函式
- 三、資料包 ON
- 四、物件Object
- 五、Promise
- 六、Async : Await
- 七、包
- 總結
一、普通函式
js的函式建立比較特殊,有很多種方式,最簡單的一種和c語言類似。
特點:
函式名字可以除了字母、數字、下劃線外,還可以存在 “$” 字元。
在js中,函式名就是一個儲存函式物件的變數。使用 typeof 關鍵字可以檢視函式型別。(這個理念和類似,可以用其他變數接手這個函式)
函式形參定義時不需要寫關鍵字:var、let、const。應該預設就是區域性可修改變數。
JS 語法中 不檢查輸入引數。這意味著,輸入引數可少可多。少了輸入undefined代替,多了自動忽略。
同上理,JS 也不拘束是否有返回值,統一都有返回值。如果沒有寫明返回值,則統一返回無效值。
// 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還支援匿名函式,就是不寫函式名。python中也有類似,在python學習筆記中也有記錄:lambda匿名函式。
// 6. 函式還可以沒名字,直接這樣建立。 let him = function(){ console.log("him"); } him() // 側面反映了,名字其實就是一個變數名。 // 8. 函式名字本身不支援傳遞賦值,但是變數可以。 // him = printHello_1(); // 報錯(有點類似陣列定義後就不能再賦值?) let add = him; add(); // 7. 該變數還是可以賦值其他內容。 him = 6; console.log(him) // 輸出數字 6
二、箭頭函式
js中箭頭函式就是“名副其實”的匿名函數了,可快速建立巢狀函式功能體(自創用詞)……也更加貼合python的lambda匿名函式用法。
在看實戰案例時全是這種匿名函式的建立和傳參,第一次接觸懵逼得不要不要的。下面的程式碼為了方便看效果,我會把用不到的部分改成假,遮蔽執行。你問為什麼不直接註釋?因為想鍛鍊用法。
使用方法看似簡單,前面括號就是用到的引數,箭頭後面緊跟程式碼。如果是單行的簡易程式碼可不用寫括號,單行還自帶隱式返回計算值。
if (false) { const add = (a,b) => a + b; // 類似直接建立函式,並且將該函式丟給一個變數呼叫。 console.log(add(1,3)); // 沒有寫返回值,還隱式返回了計算值 } if (false) { let add = (a,b) => a + b; console.log(add(1,3)); // 列印 4 const add_0 = add; // 可以正常的變數賦值替換 add = 5; // 可以看出本質還是變數,如果定義是使用可變型別,則可以改變 console.log(add); // 列印 5 console.log(add_0(2,4)); // 列印 6 } if (false) { console.log(add_0(10,4)); // const 變數型別不可以跨作用域 }
如果是需要換行,就需要用大括弧。常用。
if (false) { const add = (a,b) => { return a + b; } console.log(add(1,3)); // 有返回值,表示如果用了大括號可以表示換行但是不會有隱式返回。而單行總是會有隱式返回的。 }
三、資料包 JSON
JSON( Object Notation,JS 物件簡譜) 是一種輕量級的資料交換格式。它基於 ECMAScript (歐洲計算機協會制定的js規範)的一個子集,採用完全獨立於語言的文字格式來儲存和表示資料。簡潔和清晰的層次結構使得 JSON 成為理想的資料交換語言。 易於人閱讀和編寫,同時也易於機器解析和生成,並有效地提升網路傳輸效率。【截至百科】
- 在之前學習神經網路和ros時也有接觸這類資料包,一個小小的字尾.json檔案,裝著一堆引數或資料集。從格式上看,很像字典,有鍵和值成對。如果展開圖形化,其實是一個列表,有表頭和資料。
- js提供Object類來建立json物件。(其實就是建立物件,下一節再細說)
// 例子1
if (false)
{
const book = new Object({title : "1984",author : "George Orwell"}) // 建立 JSON 物件
console.log("\n ---------")
console.log(typeof book) // 檢視型別,確實是物件
console.log(book) // 能正常列印
}
// 例子2(下一節細說,物件的知識點)
ihttp://www.cppcns.comf (false)
{
const book = ({title : "1984",author : "George Orwell"}) // 就算不加關鍵詞 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) // 列印型別還是物件 object,但是實際上一個算是陣列
console.log(book)
}
- js提供將json物件資料轉換為字串的方法:
JSON.stringify()。
if (false) { const book = ({title : "1984",author : "George Orwell"}) // 就算不加關鍵詞 Object 也能有相同效果。 console.log("\n ---------") let bookJSON = JSON.stringify(book); // 將物件保留原本格式,轉換為了字串,其中鍵名變成了字串(就是加了雙引號)?方便用於儲存在文字內? console.log(typeof bookJSON) // 想起來,JSON不也是之前我寫ros工程時用到的引數檔案嗎,還有百度飛漿的文字檔案都是這種格式。 console.log(bookJSON) } /* 輸出內容如下: --------- string {"title":"1984","author":"George Orwell"} */ // 可以發現鍵值還是原本的字串,但是鍵名已經變換為字串
我做了一個類比實驗,看如下注釋。
if (false) { const book = ([1,23,3,"156"]) console.log("\n ---------") console.log(typeof book) // 型別依舊屬於 object let bookJSON = JSON.stringify(book); // 依舊可以呼叫,不會出現報錯。 console.log(typeof bookJSON) // 得到的結果 和原結果一模一樣的字串。 console.log(bookJSON) } /* 輸出內容如下: --------- object string [1,"156"] */ // 可以發現函式好像沒有起到作用。判斷格式不符合json要求時不會起作用,也不會報錯。
js提供將字串資料轉換為json物件的方法:JSON.parse()。
就是JSON.stringify()
的逆操作了。
if (false) { let data_0 = "[1,2,3]"; let data = "{\"title\" : \"1984\",\"author\" : \"George Orwell\"}"; // 注意,JSON的字串形式下,鍵和值都是要加雙引號的,弄成類似字串的形式。有一點不對都會轉換失敗。 let parsed = JSON.parse(data); // 逆向操作,將字串再變回成物件型別。會解析是否符合格式。 console.log("\n -----") console.log(parsed); // console.log(typeof parsed) console.log(typeof data) } /* 輸出內容如下: ----- { title: '1984',author: 'George Orwell' } object string */ // 需要注意的就是字串中的斜杆表示比較麻煩
- 學習JSON格式資料的使用非常重要,json變數其實並非普通的資料,而是包含眾多資料處理函式的物件。比如上述2個字串和資料之間相互轉換的函式,檢查在實戰中用到。分別是讀取資料和儲存資料的2個操作。
四、物件Object
js中的物件建立不同於python的類,而是直接建立物件。我直接看例子,結合例子展開。
if (false) { let data_0 = "[1,author: 'George Orwell' } object string */ // 需要注意的就是字串中的斜杆表示比較麻煩
從格式可以看出,感覺是一堆屬性,有字串,有匿名函式。而且不是用等於號而是用冒號賦值,就像字典的鍵對一樣。
所以現在看來,其實json資料包,在js中相當於物件的存在。如果是直接列印函式方法,會輸出類似字元:[Function (anonymous)]。
除了一開始直接賦值,也可以採用先建立空物件,再逐步新增值。如果已經存在的屬性會覆蓋,否則就當作是新增。(很簡單粗暴)
// 2. 另一種建立物件的方法,使用建構函式建立 if (false) { const book = new Object(); console.log(book); // 一開始建立是空的 console.log(typeof book); //型別是 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. 訪問物件內元素的方法: console.log(book.title); // 類似結構體的訪問 console.log(book["title"]); // 類似字典的訪問,輸出結果是一樣的,注意,這樣訪問的話,鍵名一定要加雙引號,看作字串形式 console.log(book.checkIn); // 如果是訪問函式,如果不加括號,會返回物件。列印類似字元:[Function (anonymous)] console.log(book.checkIn()); // 如果加括號就相當於呼叫執行.(返回值空,因為函式內沒用寫返回值) console.log(book["checkIn"]); // 也可以使用字典的形式訪問,結果一樣 console.log(book["checkIn"]()); // 就是這個括號是在方括號外面的。 }
- 上下文機制: this,並不完全是在物件內值指物件的名字,而是指代上下文使用的變數?(具體看視訊講解,我理解還不太透徹)
- 類似於我使用的主體,我使用的主體是物件,返回的就是物件,我使用的函式,返回的就是函式。所以this還可以在函式中使用,雖然函式本身也是一個物件(?)。
if (false) { const bookObj = { // 建立一個物件 checkIn : function(){ // 新增一個屬性 return this; // 這個屬性是一個方法,且有返回值,返回物件本身 } } function anotherCheckIn(){ // 建立一個函式 return this; // 返回一個函式本身 } console.log(bookObj.checkIn() == bookObj); // 返回值是不是物件本身,對的 console.log(bookObj.checkIn() == globalThis); // 返回值是不是函式,錯的 console.log(anotherCheckIn() == globalThis); // 返回值是不是函式,對的 }
五、Promise
懵逼的一節,講js中的非同步執行機制?不多解釋,怕越說越錯。
// Promise 物件用於表示一個非同步操作的最終完成 (或失敗)及其結果值。
if (true)
{
function promiseTimeout(ms){ // 建立一個函式
return new Promise((resolve,reject) => { // 返回一個 Promise 物件, 輸入引數是一個匿名函式,其中匿名函式又有2個引數,一個是成功時會執行的內容,一個是失敗時會執行的內容
setTimeout(resolve,ms); // js內部函式,延時第二個引數ms後執行 第一個引數的內容。
});
}
promiseTimeout(2000) // 呼叫函式,傳入引數2000ms;
.then(() => { // 返回的 Promise 物件的內建方法;如果成功則會呼叫。該內建方法也有一個引數,該引數是匿www.cppcns.com名函式
console.log('Done!!'); // 該匿名函式無參入引數,內部功能只有列印
return promiseTimeout(1000); // 再呼叫一次函式,又返回一個變數
}).then(() => { // 因為上面又返回了一個變數,所以可以鏈式呼叫,
console.log('Also done!!'); // 延時1000ms,執行成功後會接著呼叫
return Promise.resolve(42); // 又返回一個物件,無限套娃
}).then((result_0) => { // 傳入引數,這個引數名字是隨意的,我修改後還是能實現效果。ide自動標紅,應該能知道是變數,而非語法關鍵字
console.log(result_0); // 列印引數
})
.catch(() => { // 同上,不過是失敗時呼叫
console.log('Error!');
})
// 因為 Promise.prototype.then 和 Promise.prototype.catch 方法返回的是 promise, 所以它們可以被鏈式呼叫。
}
/*
執行結果為:
先稍等一會列印一行:
Done!
稍等片刻後再同時先後列印兩行:
Also done!
42
*/
六、Async : Await
和Promise機制相反。
// 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關鍵字,結果類似去同步執行。本來使用Promise會使先列印,後延時,如果加上A/A後就會按順序先延時再列印。 const response = await longRunningOperation(); console.log(response); // 按道理應該直接返回42並列印,實際上,如果不加await關鍵字,會立刻返回一個Promise物件,而不是42. console.log('Stop!!'); } run(); /* 執行結果為: 先列印一行: Start! 稍等片刻後再同時先後列印兩行: 42 Stop! */
七、包
使用node.js中附帶的nvm工具,可以很好的管理js軟體包。而且工程可以配備了相關軟體包目錄。只需要在其中新增對應軟體包,再輸入更新工程指令就可以在工程中新增軟體包。
類似於編譯一樣,不過這個是下載。過去python提倡將軟體包直接安裝在電腦工作環境空間內。而c語言的相關庫是建議在工程內。js也是提倡在工程內。不過如果要轉移程式時,會講軟體包資料夾刪除。只轉移工程程式碼部分。轉移完畢後在別的電腦上再使用更新下載功能即可。這個操作有點像之前學過的ros工程。不過ros工程就算不設定正確也能正常執行,js如果設定不準確,在編譯時就不通過了。
總結
本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注我們的更多內容!