2010-02-03 81 views
1

在某些情況下,此代碼有效。如果它返回console.log那麼致電p.out功能就好了。如何返回內置函數作爲對象屬性?

function Notice(mode) { 
    this.debug = mode; 

    this.out = (function() { 
      if(mode) { 
       if(window.console) { 
        return console.log; 
       } else { 

        return alert; 
       } 
      } else { 
       return Notice.doNothing; 
      } 
    })(mode); 
} 

var p = new Notice('1'); 
p.out('Kool-aid, OH YEAH!'); 

然而,當它返回警報(或window.alert)我得到一個錯誤:

Error: uncaught exception: [Exception... "Illegal operation on WrappedNative prototype object" nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" location: "JS frame :: http:// .. :: <TOP_LEVEL> :: line 22" data: no] 

而作爲一個簡單的測試,這個工程:

out = (function() { return alert; })(); 
out('hello dolly'); 

我怎麼能當obj.out設置爲alert時,它會正常運行嗎?

+0

您的例子不工作在FF例外。 – 2010-02-03 09:45:41

+0

什麼版本?這個錯誤是從FF3.5 - 最高的例子有錯誤,而不是底部的兩個班輪。 – Stomped 2010-02-03 09:48:37

+0

它在IE 8中也能正常工作...... – RameshVel 2010-02-03 09:52:30

回答

3

爲什麼不返回一個匿名函數,作爲回報調用內置函數?

喜歡的東西

return function(msg) { alert(msg); } 
+0

這是一個很好的解決方法,但我覺得很奇怪,我可以將它分配給一個簡單的變量,但不是屬性..這只是一個變量。 – Stomped 2010-02-03 09:45:38

+0

是的。我的猜測是屬性比正常變量更嚴格。也許一位看到這個問題的JS大師可以解釋爲什麼以及如何。 – 2010-02-03 09:47:22

+0

@ESW:查看我爲什麼一個屬性與變量不同的答案。 – slebetman 2010-02-03 09:55:53

1

我懷疑你遇到的問題是不是因爲你是如何設置它,但由於職能參與其中。 console.log調用log函數,其上下文(this值)設置爲console。如果你

var f = console.log; 
f("Hi there"); 

...注意log是帶一個不同的上下文(在這種情況下,全局對象,這是在瀏覽器window),this不再是console對象。

如果你這樣做:

var obj = {}; 
obj.f = console.log; 
obj.f(); 

...然後log將與objthis調用。

某些功能會很在意,因爲某些功能在其實現中使用this。有些功能不會關心,因爲它們不會。這可能是因爲alert並不在意,因爲它恰巧期待thiswindow - 這正是您調用raw函數時的情況(例如,不是通過點符號或其他明確設置的方式this),因爲(再次)window是瀏覽器中的全局對象。

作爲一個單獨的說明:在大多數實現中,您看到的內置函數都是正確的JavaScript函數對象並具有其所有功能。在某些實現中,儘管(Internet Explorer是一種),但它們根本不是正確的JavaScript函數,它們缺少適當功能的某些功能,例如applycall屬性。如有疑問,請換行。

5

問題是,在某些實現中,alert實際上是窗口對象的一個​​正確方法。也就是說,警報預計this是窗口對象。這說明在最簡單的形式問題:

var foo = {alert : alert}; 

/* this fails because the value of 'this' is foo: 
*/ 
foo.alert('hello'); 

/* but this works because we re-point 'this to the 
* correct object, that is the window object: 
*/ 
foo.alert.call(window,'hello'); 

所以,你的問題的解決方案是要麼返回直接打電話警告或綁定窗口的關閉提醒功能。要麼是這樣的:

function Notice (mode) { 
    this.out = function(message) { 
     if(mode) { 
      if(window.console) { 
       console.log(message); 
      } else { 
       alert(message); 
      } 
     } 
    }; 
} 

或本:

function Notice (mode) { 
    this.out = (function() { 
     if(mode) { 
      if(window.console) { 
       return console.log; 
      } else { 
       return function (message) {alert(message)}; 
      } 
     } 
    })();   
} 
+0

'(function(){..})()'格式更好,因爲它不必每次發送消息時都要確定發送消息的位置。這個解釋非常好,但是很有幫助。 +1 – Stomped 2010-02-03 09:59:58

+0

啊!很有意思。謝謝。 +1 – 2010-02-03 10:58:54