2 回答

TA貢獻1877條經驗 獲得超6個贊
面向對象語言來說,舉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類型的對象,baz里面的this指向的是InnerFoo類型的對象,而baz2里面的Foo.this指向的是外層的Foo類型的對象,所以需要用Foo來限定。
其實把對象本身作為參數顯式的傳入并不是什么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綁定的問題,比如用var that = this然后引用that就是一個常用的方法。
函數編程里雖然沒有this變量作為隱含參數傳入,但是事實上是有更有效的工具的:閉包(closure)。事實上this變量可以算是閉包的一種情況。而在一些dynamic scoping的語言(如elisp)里面,函數的運行依賴于調用環境,所以“隱含的參數”其實更多。
我個人的看法是,面向對象里面為了方便(或者強調)封裝(encapsulation),把數據和操作綁定在一起,“this”的地位才如此重要。而函數編程語言中,第一公民是函數(操作)而不是數據,所以并沒有this的地位。這兩者是不同的思維范式,取長補短即可。

TA貢獻1810條經驗 獲得超4個贊
從forEach
這個具體的例子來看,問題倒比較容易解決,畢竟
Array.forEach(callback[, thisArg])
里可以直接將外層的this
傳入,這樣就解決了。
從更一般的角度來看,以我愚見,定義一個var this_
,雖然不太好看,但是在需要多次使用外層的this
的時候,還是很方便的。
如果不需要多次使用this
的話,Function.bind
也可以在一定程度上解決這個問題。
想要根本上解決這個問題,也可以考慮在每個構造函數里加入類似這樣的代碼:
// methodNames是一個包含所有方法名稱的ArraymethodNames.forEach(function(name) { this[name] = this[name].bind(this) }, this);
缺點是這么做會大大降低運行效率,而且也不好看。
總的來說這是Javascript
的設計上的問題,只能繞過去了。
如果是用CoffeeScript的話,那么可以使用它提供的=>
來定義一個保留外層this
的函數:
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()
這個功能看起來還是不錯的..
添加回答
舉報