我只是想用JavaScript寫一個方法...

JavaScript中定義一個方法主要能夠分紅兩種形式:javascript

  • 函數聲明
  • 函數表達式

函數聲明

聲明體是最普通的,與其餘語言也相近的一種方式。java

function func(a, b) {
  return a + b
}

func(1, 2) // 3
複製代碼

不過,畢竟JavaScript!它有一個特性:函數提高。編程

函數提高:把全部函數提高到當前做用域上,從而能夠作到「未聲明先調用」。函數式編程

(劃重點!等下要考!)函數

函數表達式

這多是目前用的最多的聲明方式,由於能夠搭配箭頭函數「僞裝本身在用函數式編程」。ui

const func = function(a, b) {
  return a + b
}

// 箭頭函數版本
const funcA = (a, b) => a + b

func(1,2) // 3
複製代碼

但受變量做用域的關係,因此constlet沒有變量提高的能力。this

funcA(1) // ReferenceError: funcA is not defined
const funcA = a => a
複製代碼

燃鵝,這纔剛剛開始…spa

函數表達式:匿名 & 具名

匿名就是上面那種,而具名就是給函數本體再起一個名字。code

const func = function funcName() {}
複製代碼

這樣有什麼用?後面那個名字又不能用!答案仍是有區別的。對象

首先有一個函數名推斷,例如上面這個函數,那麼func.name會返回funcName,若是匿名函數的話[fn].name會返回''(在ES5的狀況下,ES6會被推斷爲外面的函數名)。其次這個名字能夠在函數內部使用,固然了指代的就是本身了。

const func = function funcName(a, b) {
  return a < 0 ? b : funcName(a+1-b, a)
}

func(431, 151) // 281
funcName(431, 151) // ReferenceError: funcName is not defined
console.log(func.name) // funcName
typeof funcName === 'function' // false
複製代碼

因此這種方式最適合遞歸函數了。

函數表達式依然是個常/變量

關鍵詞已經決定了這個「量」會以什麼形式存在,好比varlet是變量,const是常量,而且let還有做用域範圍。

const funcA = () => console.log('A')
funcA() // A
funcA = () => console.log('AA') // TypeError: Assignment to constant variable.

var funcB = () => console.log('B')
funcB() // B
funcB = () => console.log('BB')
funcB() // BB
複製代碼

題外話:那麼就有個老生常談的問題了,函數表達式按道理來說是「靈活的」,那麼

function funcB() {
  console.log('B')
}
funcB()
function funcB() {
  console.log('BB')
}
funcB()
複製代碼

兩個funcB的結果分別會是什麼?

箭頭函數

又到了你們最最喜歡的箭頭函數環節,如今還有誰是不肯意寫箭頭函數的?

const func = a => b => a + b
func(1)(2) // 3
複製代碼

不過,箭頭函數兩個特色:

  • 不會創造上下文(自身無this
  • 必然是個匿名函數
  • 沒有 arguments

不是兩點嗎?怎麼變成三點了?此時你可能會回去檢查剛剛那句話,可是我如今悄悄告訴你,實際上是三點。

關於箭頭函數自身無this,有不少文章講了this的指向相關,能夠翻看那些文章獲得答案。

計算屬性函數名

這個應該是在「對象」的環境中存在,畢竟對象能夠指代不少種只要是對象的狀況。

const object = {
  ['a' + 'b'](a, b) {
    return a + b
  }
}

object.ab(1, 2) // 3
複製代碼

這就實現了「函數名能夠暫時不知道是什麼」的狀況,經過計算來獲得這個函數。

Other

new Function

這是一個不知道哪裏能夠用得上可是能夠用的方式:經過對象建立

const func = new Function('a', 'b', 'return a + b')
func(1, 2) // 3
複製代碼

函數參數初始值

可能會有參數要初始值的需求,但可能沒有

function func(a = 1, b = 2) {
  return a + b
}

func() // 3
複製代碼

可能咱們更經常使用的還有這些

const funcA = (obj = {}) => obj

const funcB = (arr = []) => arr
複製代碼

JavaScript畢竟是「函數是第一公民」的語言,有機會會寫到不少高階函數。因此

const func = (fn = () => 'YDJFE') => fn.call(null)
複製代碼

憑什麼函數做爲參數就不能有初始值呢?固然是能夠的呀!

總結

我只是想用JavaScript寫一個方法…爲何這麼複雜…

(關於JavaScript定義方法,若是還有其餘姿式歡迎補充~)

相關文章
相關標籤/搜索