Javascript lexical functional scope,姐係variable嘅lifespan係一個個function咁計,每當有一個新function,就有一個新嘅scope。
另一個javascript嘅特點係first-class function姐係function可以係一個variable type,個function可以pass入第2個function,或姐一個function return另一個function.E一個特點令javascript好多時都會用到callback function E個pattern.
以上2個特點加埋一齊就會出現一D麻煩。
例如callback function入邊個this
有時會唔小心指左去第2個scope。
1 | app.name = 'my app' |
以上果段code個this就會指左去jQuery個scope。當callback function入邊有用到this
果時,咁就會有D unexpected behaviour出現。以上例子中嘅this.name
會指左去$.name
,而唔係app.name
。
有D人可能會諗
Callback果度用
app.name
唔好用this.name
咪得囉。
E個solution有2個缺點
- hardcode caller個variable name會少左flexibility。
有時後個callback可以用係唔同地方,但係一要hardcode個caller variable入去,個callback就變左context specific,廢左武功,冇得reuse。咁當然可以用D wrapper 去fix E 個problem,但係就要寫好多boilerplate code,搞到段code好冗長。 - abstract唔到個function interface做一個API
其實一個function已經係一個abstraction,當個user 入個callback去call你個function,佢suppose唔洗知你個function點implement。以上文為例,人地跟本唔知你用jQuery咁樣implement,唔知道用this
會有bug。咁樣寫getUsers係做唔到一個public api。
咁點樣寫先啱?個問題主要係function個scope冇清淅define,只要我地用一D native javascript function指定返個this
就得。例如:
1 | app.getUsers = function( callback ){ |
callback.call( self, data )
第一個argument就係指定左個this
係做self
,姐係call緊self.callback(data)
。
又或者可以用callback.apply( self, [data] )
,姐係call緊self.callback(data[0], data[1], data[2] ...)
。
都可以用(callback.bind(self))(data)
,bind
都係指定個this,但係佢唔會直接行個function,而係return一個bind左scope嘅function。
總結
- 當implement callback pattern,要記住留意this嘅binding。
- 當要借其他object D method用,最好用call,apply或者bind,因為我地唔知人地點implement。
- 如果只需要借人地D method用一次,直接用
call
或apply
就得。如果唔係馬上call或者要用幾次,最好用bind
create一個新function先。