JavaScript基礎(chǔ)系列之函數(shù)和方法詳解
一、函數(shù)和方法的區(qū)別
- 函數(shù)(function):函數(shù)是帶有名稱和參數(shù)的 JavaScript 代碼段,可以一次定義多次調(diào)用。
- 方法(method):當(dāng)將函數(shù)和對(duì)象寫在一起時(shí),函數(shù)就變成了“方法”,比如當(dāng)函數(shù)賦值給對(duì)象的屬性時(shí),我們便稱其為“方法”。
二、如何寫好一個(gè)函數(shù)
在 JS 中,除了變量,用的最多的應(yīng)該就是函數(shù)了,函數(shù)是 Javascript 的第一公民。
2.1 命名準(zhǔn)確
2.1.1 函數(shù)命名
函數(shù)的命名需要明確,語(yǔ)義清晰,簡(jiǎn)單概括函數(shù)的功能。我們不要想著代碼簡(jiǎn)短而縮短函數(shù)名稱,這并不會(huì)提高什么性能或效率,相反,一個(gè)函數(shù)名稱若不夠清晰,往往其他人無(wú)法理解。
盡量使用動(dòng)詞,比如:getXxxxx、setXxxxx,動(dòng)詞在前面,語(yǔ)義就能更加清晰。
2.1.2 參數(shù)命名
強(qiáng)調(diào)語(yǔ)義化,參數(shù)命名讓調(diào)用者更清晰的知道該傳入什么,對(duì)應(yīng)什么參數(shù)。當(dāng)然,像一些通用命名還是可接受的,像 callback,fn,即使不看注釋,往往我也知道這里的參數(shù)要做什么,傳什么。
2.2 函數(shù)注釋
/** * 時(shí)間格式化工具函數(shù) * * @param { (Date | number) } date - 時(shí)間 * @param { string } unit - 轉(zhuǎn)換格式 */ export const timeFormat = (date: Date | number | string, unit: string) => { if (!date) { return '' } if (typeof date === 'string') return date; if (typeof date === 'number') { date = new Date(date); } const year = date.getFullYear(); const month = date.getMonth() + 1; const day = date.getDate(); const hour = date.getHours(); const minute = date.getMinutes(); const second = date.getSeconds(); if (unit === 'year') return `${year}`; if (unit === 'month') return `${year}-${month}`; if (unit === 'day') return `${year}-${month}-${day}`; if (unit === 'hour') return `${year}-${month}-${day} ${hour}`; if (unit === 'minute') return `${year}-${month}-${day} ${hour}:${minute}`; if (unit === 'second') return `${year}-${month}-${day} ${hour}:${minute}:${second}`; }
2.2.1 參數(shù)注釋
/** * 時(shí)間格式化工具函數(shù) * * @param { (Date | number) } date - 時(shí)間 * @param { string } unit - 轉(zhuǎn)換格式 */
@param { type } 參數(shù) - 參數(shù)解釋:type 表明的是參數(shù)的類型,比如 string,number,當(dāng)有多個(gè)參數(shù)類型的時(shí)候,可以這么來(lái)標(biāo)識(shí) { (string|string[]) },表示這個(gè)參數(shù)可以是字符串或者字符串?dāng)?shù)組。
對(duì)象屬性:需要解釋對(duì)象的每一個(gè)屬性
/** * 將項(xiàng)目分配給員工的函數(shù) * * @param {Object} employee - 項(xiàng)目員工 * @param {string} employee.name - 項(xiàng)目員工的姓名 * @param {string} employee.department - 項(xiàng)目員工的部門 */ Project.prototype.assign = function(employee) { // ... };
可選參數(shù):
/** * 時(shí)間格式化工具函數(shù) * * @param { (Date | number | string) } date - 時(shí)間 * @param { string } [unit] - 轉(zhuǎn)換格式 */ export const timeFormat = (date: Date | number | string, unit: string) => { // ... }
默認(rèn)值:
/** * 時(shí)間格式化工具函數(shù) * * @param { (Date | number) } date - 時(shí)間 * @param { string } [unit = 'second'] - 轉(zhuǎn)換格式 */ export const timeFormat = (date: Date | number | string, unit = 'second') => { // ... }
2.3 函數(shù)參數(shù)
2.3.1 參數(shù)默認(rèn)值
export const timeFormat = (date: Date, unit = 'second') => { // ... }
2.3.2 對(duì)象參數(shù)
async function printer_proxy_print( html_str: string, file_path: string, device: string | undefined, orientation: number, printer_mode: string, width: number, height: number, scale: number, from: number, to: number, left_offset: number, top_offset: number, pdf_tools: string | undefined, begin_page = 1, end_page = 1, repeat_times = 1, print_type: string ) { // ... }
可以給參數(shù)默認(rèn)值,這樣可以只傳前面幾個(gè)必要的參數(shù),像這樣調(diào)用。
async function printer_proxy_print( html_str: string, file_path: string, device = 'pc', orientation = 'xxx', printer_mode = 'xxx', width = 123, height = 123, scale = 123, from = 123, to = 123, left_offset = 123, top_offset = 123, pdf_tools = 123, begin_page = 1, end_page = 1, repeat_times = 1, print_type = 'base64' ) { // ... } await printer_proxy_print(html_str, file_path);
上面的方法看似可行,實(shí)際上,當(dāng)我中間某個(gè)參數(shù)不一樣的時(shí)候,我就需要把這個(gè)參數(shù)前面的參數(shù)都傳一遍。這樣顯然不可行。所以當(dāng)參數(shù)多的時(shí)候,我們需要用對(duì)象解構(gòu)的方式傳參。
async function printer_proxy_print({ html_str, file_path, device = 'pc', orientation = 'xxx', printer_mode = 'xxx', width = 123, height = 123, scale = 123, from = 123, to = 123, left_offset = 123, top_offset = 123, pdf_tools = 123, begin_page = 1, end_page = 1, repeat_times = 1, print_type = 'base64' }) { // ... } await printer_proxy_print({html_str, file_path});
解構(gòu)的好處便是我可以隨便傳我想要的某幾個(gè)參數(shù),而不用在意順序問(wèn)題。不過(guò)像這么多參數(shù)的函數(shù)往往存在問(wèn)題(具體問(wèn)題具體分析)。也就是下面提到的參數(shù)數(shù)量問(wèn)題。
2.3.3 參數(shù)數(shù)量
一個(gè)函數(shù)的參數(shù)越少越好,最多不應(yīng)該超過(guò)3個(gè),參數(shù)多往往意味著關(guān)系多,邏輯交叉相對(duì)也就多了起來(lái)。在進(jìn)行測(cè)試的時(shí)候,往往也就很難覆蓋到所有條件,出問(wèn)題概率也就加大了。
參數(shù)多的時(shí)候,有時(shí)候也意味著功能多,就違背了 單一功能 的原則。
2.3.4 參數(shù)類型防御
在 TS 開發(fā)前,我們不知道用戶會(huì)傳什么東西進(jìn)來(lái),這時(shí)候往往容易產(chǎn)生類型錯(cuò)誤,又或者,我們想實(shí)現(xiàn)兼容,像前面的 timeFormat 函數(shù),我們希望用戶調(diào)用的時(shí)候,可以是想對(duì) 時(shí)間對(duì)象 格式化,也可以是對(duì) 時(shí)間戳 格式化,那我們就需要做一個(gè)防御處理。
if (!date) { return '' } if (typeof date === 'string') return date; if (typeof date === 'number') { date = new Date(date); }
不過(guò)值得注意的是,即使我們用上了 TS,在大多數(shù)情況下,我們確實(shí)可以避免參數(shù)類型問(wèn)題,但是這并不絕對(duì),因?yàn)槲覀冇袝r(shí)候會(huì)直接接受 接口 返回的數(shù)據(jù)。
我們常說(shuō),永遠(yuǎn)不要相信用戶的輸入,同樣,接口返回的數(shù)據(jù)我也不信,我們不能保證,后端不會(huì)出錯(cuò),約定好的參數(shù)是數(shù)組類型,怎么空的時(shí)候,你給我個(gè) null 呢?
當(dāng)然這些情況有時(shí)候需要去試錯(cuò),有時(shí)候我們能想到的可能,不要偷懶,給寫上類型判斷吧。
2.4 函數(shù)的返回
2.4.1 冪等函數(shù)
什么叫冪等,簡(jiǎn)單來(lái)說(shuō),輸入什么輸出什么是固定的,入?yún)Q定了出參,不管調(diào)用多少次,只要輸入一樣,結(jié)果應(yīng)該保持一樣。
function sum(a: number, b: number) { return a + b; }
冪等函數(shù)具有可維護(hù)性,相對(duì)容易進(jìn)行單元測(cè)試。
2.4.2 純函數(shù)
純函數(shù)在冪等的條件下,還要求沒有副作用。
const dog = { name: 'puppy', age: 2, weight: 30, } if (!dog.color) { console.log('has no color'); } function addColor(dog) { dog.color = 'white'; } addColor(dog); console.log(dog); // {name: "puppy", age: 2, weight: 30, color: "white"}
可以看到,addColor 函數(shù)修改了 dog 對(duì)象的屬性,也就是產(chǎn)生了副作用。
function addColor(dog) { let copyDog = Object.assign({}, dog); copyDog.color = 'white'; return copyDog; }
這樣一來(lái),dog 對(duì)象的屬性就不會(huì)修改,addColor 函數(shù)是純函數(shù)。
2.4.3 return null
null 在進(jìn)行處理的時(shí)候相對(duì)麻煩,需要進(jìn)行判斷,導(dǎo)致了額外的代碼,應(yīng)當(dāng)返回空對(duì)象,或者是空數(shù)組,或者拋出異常。
函數(shù)和方法的區(qū)別
1)函數(shù)(function)是一段代碼,通過(guò)名字來(lái)進(jìn)行調(diào)用。它能將一些數(shù)據(jù)(參數(shù))傳遞進(jìn)去進(jìn)行處理,然后返回一些數(shù)據(jù)(返回值),也可以沒有返回值。
2)方法(method)是通過(guò)對(duì)象調(diào)用的javascript函數(shù)。也就是說(shuō),方法也是函數(shù),只是比較特殊的函數(shù)。他是和一個(gè)對(duì)象相關(guān)聯(lián)。假設(shè)有一個(gè)函數(shù)是fn,一個(gè)對(duì)象是obj,那么就可以定義一個(gè)method:
obj.method = fn;
obj.method();
3)函數(shù)的數(shù)據(jù)是顯式傳遞
4)方法中的數(shù)據(jù)是隱式傳遞的;方法和對(duì)象相關(guān)。
總結(jié)
到此這篇關(guān)于JavaScript基礎(chǔ)系列之函數(shù)和方法的文章就介紹到這了,更多相關(guān)JavaScript函數(shù)和方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
原生javascript實(shí)現(xiàn)的全屏滾動(dòng)功能示例
這篇文章主要介紹了原生javascript實(shí)現(xiàn)的全屏滾動(dòng)功能,涉及javascript事件響應(yīng)及頁(yè)面元素屬性動(dòng)態(tài)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-09-09利用JavaScript為句子加標(biāo)題的3種方法示例
這篇文章主要給大家介紹了關(guān)于如何利用JavaScript為句子加標(biāo)題的3種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01Swiper.js實(shí)現(xiàn)移動(dòng)端元素左右滑動(dòng)
這篇文章主要為大家詳細(xì)介紹了Swiper.js實(shí)現(xiàn)移動(dòng)端元素左右滑動(dòng) ,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09javascript 構(gòu)造函數(shù)強(qiáng)制調(diào)用經(jīng)驗(yàn)總結(jié)
本文將介紹javascript構(gòu)造函數(shù)調(diào)用方面的案例應(yīng)用,需要了解的朋友可以參考下2012-12-12微信小程序組件化開發(fā)的實(shí)戰(zhàn)步驟
雖然小程序在剛推出時(shí)是不支持組件化的,但如今小程序開始支持自定義組件開發(fā),下面這篇文章主要給大家介紹了關(guān)于微信小程序組件化開發(fā)的相關(guān)資料,需要的朋友可以參考下2022-09-09ES6(ECMAScript 6)新特性之模板字符串用法分析
這篇文章主要介紹了ES6(ECMAScript 6)新特性之模板字符串用法,簡(jiǎn)單介紹了ES6模板字符串的概念、功能并結(jié)合實(shí)例形式分析了ES6模板字符串的用法,需要的朋友可以參考下2017-04-04js實(shí)現(xiàn)仿百度汽車頻道選擇汽車圖片展示實(shí)例
這篇文章主要介紹了js實(shí)現(xiàn)仿百度汽車頻道選擇汽車圖片展示,實(shí)例分析了javascript鼠標(biāo)事件操作css樣式的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-05-05