2 回答

TA貢獻(xiàn)1877條經(jīng)驗(yàn) 獲得超6個(gè)贊
面向?qū)ο笳Z(yǔ)言來(lái)說(shuō),舉Java的例子:
class Foo { boolean bar() { return this.getClass() == Foo.class; } class InnerFoo { boolean baz() { return this.getClass() == InnerFoo.class; } boolean baz2() { return Foo.this.getClass() == Foo.class; } } }
bar里面的this指向的是Foo類型的對(duì)象,baz里面的this指向的是InnerFoo類型的對(duì)象,而baz2里面的Foo.this指向的是外層的Foo類型的對(duì)象,所以需要用Foo來(lái)限定。
其實(shí)把對(duì)象本身作為參數(shù)顯式的傳入并不是什么bad practise,在Python中就是這樣約定的:
class MyClass: def __init__(self, name): self.name = name def greet(self, friend): print self.name, "says hello to", friend
所以在JS中,需要特殊的處理this綁定的問(wèn)題,比如用var that = this然后引用that就是一個(gè)常用的方法。
函數(shù)編程里雖然沒(méi)有this變量作為隱含參數(shù)傳入,但是事實(shí)上是有更有效的工具的:閉包(closure)。事實(shí)上this變量可以算是閉包的一種情況。而在一些dynamic scoping的語(yǔ)言(如elisp)里面,函數(shù)的運(yùn)行依賴于調(diào)用環(huán)境,所以“隱含的參數(shù)”其實(shí)更多。
我個(gè)人的看法是,面向?qū)ο罄锩鏋榱朔奖悖ɑ蛘邚?qiáng)調(diào))封裝(encapsulation),把數(shù)據(jù)和操作綁定在一起,“this”的地位才如此重要。而函數(shù)編程語(yǔ)言中,第一公民是函數(shù)(操作)而不是數(shù)據(jù),所以并沒(méi)有this的地位。這兩者是不同的思維范式,取長(zhǎng)補(bǔ)短即可。

TA貢獻(xiàn)1810條經(jīng)驗(yàn) 獲得超4個(gè)贊
從forEach
這個(gè)具體的例子來(lái)看,問(wèn)題倒比較容易解決,畢竟
Array.forEach(callback[, thisArg])
里可以直接將外層的this
傳入,這樣就解決了。
從更一般的角度來(lái)看,以我愚見(jiàn),定義一個(gè)var this_
,雖然不太好看,但是在需要多次使用外層的this
的時(shí)候,還是很方便的。
如果不需要多次使用this
的話,Function.bind
也可以在一定程度上解決這個(gè)問(wèn)題。
想要根本上解決這個(gè)問(wèn)題,也可以考慮在每個(gè)構(gòu)造函數(shù)里加入類似這樣的代碼:
// methodNames是一個(gè)包含所有方法名稱的ArraymethodNames.forEach(function(name) { this[name] = this[name].bind(this) }, this);
缺點(diǎn)是這么做會(huì)大大降低運(yùn)行效率,而且也不好看。
總的來(lái)說(shuō)這是Javascript
的設(shè)計(jì)上的問(wèn)題,只能繞過(guò)去了。
如果是用CoffeeScript的話,那么可以使用它提供的=>
來(lái)定義一個(gè)保留外層this
的函數(shù):
class Tree constructor: (@value, @children) -> show: () -> @children.forEach (child) => # Note the fat arrow (=>) used here console.log "<Tree %s %s>", @value, child t = new Tree "root", [1, 2, 3] t.show()
這個(gè)功能看起來(lái)還是不錯(cuò)的..
添加回答
舉報(bào)