2010-04-11 11 views
7

मैं अपने लॉगिंग स्टेटमेंट को यथासंभव छोटा रखना चाहता था जबकि कंसोल को अस्तित्व में रखने से रोकने के दौरान; मैं निम्नलिखित समाधान के साथ आया था:किसी अन्य ऑब्जेक्ट (वेबकिट समस्या) पर console.log को असाइन करना

var _ = {}; 
if (console) { 
    _.log = console.debug; 
} else { 
    _.log = function() { } 
} 

मेरे लिए, यह काफी सुंदर लगती है, और यह (लाइन नंबर कि console.debugconsole.log की तुलना में अधिक उपयोगी बनाने के संरक्षण सहित) Firefox 3.6 में महान काम करता है। लेकिन यह सफारी 4 में काम नहीं करता है। [अद्यतन: या क्रोम में। तो मुद्दा Firebug और वेबकिट कंसोल के बीच एक अंतर हो रहा है] अगर मैं

console.debug('A') 
_.log('B'); 

के साथ ऊपर का पालन पहले बयान दोनों ब्राउज़र में ठीक काम करता है, लेकिन दूसरा एक उत्पन्न करता है। "लेखन त्रुटि: प्रकार त्रुटि" में सफारी। क्या फ़ायरबग और सफारी वेब डेवलपर टूल्स कंसोल को कार्यान्वित करने के बीच यह एक अंतर है? यदि ऐसा है, तो ऐप्पल के वेबकिट के हिस्से पर बहुत परेशान है। कंसोल फ़ंक्शन को प्रोटोटाइप पर बाध्य करना और फिर ऑब्जेक्ट पर सीधे बाध्य करने के बजाय तत्काल, मदद नहीं करता है।

मैं निश्चित रूप से console.debug को _.log पर असाइन किए गए अज्ञात फ़ंक्शन से कॉल कर सकता हूं, लेकिन फिर मैं अपनी लाइन संख्या खो दूंगा। कोई अन्य विचार?

+0

यह वेबकिट की एक विशेषता है, एक बग नहीं ;-) https://bugs.webkit.org/show_bug.cgi?id=20141 –

+0

संबंधित: http://stackoverflow.com/questions/14146316/why-does-scope-reduction-in-safari-break-existing-code – MvG

उत्तर

8

सबसे पहले, यदि console वास्तव में अनिर्धारित है (क्योंकि यह आईई जैसे ब्राउज़र में है), तो आपको एक त्रुटि मिल जाएगी। आपको वैश्विक ऑब्जेक्ट की संपत्ति के रूप में इसकी जांच करनी चाहिए, जो ब्राउज़र में window है। इसका उपयोग करने से पहले एक फीचर का परीक्षण करने के लिए आम तौर पर एक अच्छा विचार भी है, इसलिए मैंने debug विधि के लिए एक परीक्षण जोड़ा है।

संभवतः सफारी में console.debug के कार्यान्वयन thisconsole के लिए एक संदर्भ है, इस स्थिति में अगर आप का उपयोग कर _.log (this बजाय _ के लिए एक संदर्भ हो जाएगा) इसे कहते नहीं होगा होने के अपने मूल्य पर निर्भर करता है। एक त्वरित परीक्षण किया है, इस मामले होने लगते है और निम्नलिखित फिक्स समस्या:

var _ = {}; 
if (typeof window.console != "undefined" 
     && typeof window.console.debug == "function") { 
    _.log = function() { 
     window.console.debug.apply(window.console, arguments); 
    } 
} else { 
    _.log = function() { } 
} 
+3

ठीक है, यह पारंपरिक दृष्टिकोण है, लेकिन इसमें गंभीर दोष है: यह लाइन खो देता है संख्या। यदि आप ऐप में कहीं से भी _.log() को कॉल करते हैं, तो कंसोल उस स्रोत को _.log() फ़ंक्शन के भीतर से उत्पन्न होने के रूप में रिपोर्ट करेगा, मूल स्रोत नहीं। तो console.log() के बजाय console.debug() का उपयोग करने का लाभ खो गया है। –

+2

उस स्थिति में, किसी भी उपनाम या रैपर के बिना 'कंसोल' का उपयोग करना आसान नहीं होगा, और अगर यह अस्तित्व में नहीं है तो बस इसे स्टब विधियों के साथ परिभाषित करें? उदाहरण के लिए: 'अगर (typeof window.console! = "अपरिभाषित") {window.console = {डीबग: फ़ंक्शन() {}}} 'आदि –

+0

मुझे लगता है कि आप सही हैं, टिम (हालांकि आपका मतलब है' टाइपफ विंडो .console == "अपरिभाषित" '' = 'के बजाय, सही है?)। मुझे शायद आवश्यकतानुसार एक डमी कंसोल असाइन करने के पक्ष में ब्रेवटी के लिए मेरी खोज छोड़नी चाहिए। –

0

मैं इस अपने आप के लिए एक समाधान के लिए देख रहा है (यह कैसे मैं अपने प्रश्न पाया है)।

जैसे ही टिम ने बताया, वेबकिट ब्राउज़र (सफारी, क्रोम) इस मामले में console पर भरोसा करते हैं। फ़ायरफ़ॉक्स, हालांकि, नहीं करता है। तो एफएफ में आप फ़ंक्शन को पुन: असाइन कर सकते हैं और लाइन नंबरों को संरक्षित कर सकते हैं (अन्यथा सभी लॉग दिखते हैं जैसे वे लॉगिंग फ़ंक्शन में उत्पन्न हुए हैं, जो बहुत उपयोगी नहीं है)। यह जांचने का सबसे अच्छा तरीका है कि आप कौन सा ब्राउज़र कर रहे हैं और परिणाम जांचें। ,

# Check to see if reassigning of functions work 
f = console.log 
assignSupported = true 
try 
    f('Initializing logging...') 
catch e 
    assignSupported = false 

बाद में जब आप कर कार्यों assignSupported की जाँच करें और उसके अनुसार कार्य: यहां तरीका देखें: (Coffeescript में) यह जाँच करने के लिए है

levels = 
    ERROR: 1 
    WARN: 2 
    LOG: 3 
    INFO: 4 
    DEBUG: 6 

log.setLevel = (newLevel) -> 
    for label, level of levels 
    if level > newLevel # Skip low levels 
     continue 

    name = label.toLowerCase() 
    f = -> # Fallback - empty function. In Js: var f = function() {} 
    if console?[name] 
     if assignSupported 
     f = console[name] # Wee, we'll have line numbers. 
     else 
     # Webkit need the this of console.log (namely, console) 
     # preserved, so we use a wrapper. 
     # 
     # Calling console[name] within the returned wrapper 
     # makes [name] a subject of the closure, meaning 
     # that it's the last value in the iteration - 
     # we need to preserve it. 
     f = ((n) -> 
      return (-> console[n].apply(console, arguments)))(name) 
    log[name] = f 

log.setLevel levels.DEBUG 

लाइनों:

f = ((n) -> 
    return (-> console[n].apply(console, arguments)))(name) 

लग सकता है थोड़ा सा अजीब। ऐसा इसलिए है क्योंकि name लूप वैरिएबल है और यह स्पष्ट रूप से बाध्य है, जिसका अर्थ है कि निष्पादन के समय मूल्य का उपयोग किया जाएगा, जो हमेशा अंतिम level होगा।यह इस जावास्क्रिप्ट को संकलित करता है (मामले में इसे पढ़ने के लिए आसान है):

f = (function(n) { 
    return (function() { 
    return console[n].apply(console, arguments); 
    }); 
})(name); 
संबंधित मुद्दे