javascript - Assigning console.log to another object (Webkit issue) - Stack Overflow

I wanted to keep my logging statements as short as possible while preventing console from being accesse

I wanted to keep my logging statements as short as possible while preventing console from being accessed when it doesn't exist; I came up with the following solution:

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

To me, this seems quite elegant, and it works great in Firefox 3.6 (including preserving the line numbers that make console.debug more useful than console.log). But it doesn't work in Safari 4. [Update: Or in Chrome. So the issue seems to be a difference between Firebug and the Webkit console.] If I follow the above with

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

the first statement works fine in both browsers, but the second generates a "TypeError: Type Error" in Safari. Is this just a difference between how Firebug and the Safari Web Developer Tools implement console? If so, it is VERY annoying on Apple's Webkit's part. Binding the console function to a prototype and then instantiating, rather than binding it directly to the object, doesn't help.

I could, of course, just call console.debug from an anonymous function assigned to _.log, but then I'd lose my line numbers. Any other ideas?

I wanted to keep my logging statements as short as possible while preventing console from being accessed when it doesn't exist; I came up with the following solution:

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

To me, this seems quite elegant, and it works great in Firefox 3.6 (including preserving the line numbers that make console.debug more useful than console.log). But it doesn't work in Safari 4. [Update: Or in Chrome. So the issue seems to be a difference between Firebug and the Webkit console.] If I follow the above with

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

the first statement works fine in both browsers, but the second generates a "TypeError: Type Error" in Safari. Is this just a difference between how Firebug and the Safari Web Developer Tools implement console? If so, it is VERY annoying on Apple's Webkit's part. Binding the console function to a prototype and then instantiating, rather than binding it directly to the object, doesn't help.

I could, of course, just call console.debug from an anonymous function assigned to _.log, but then I'd lose my line numbers. Any other ideas?

Share Improve this question edited Apr 13, 2010 at 0:41 Trevor Burnham asked Apr 11, 2010 at 23:51 Trevor BurnhamTrevor Burnham 77.5k33 gold badges164 silver badges199 bronze badges 2
  • It's a feature of webkit, not a bug ;-) bugs.webkit/show_bug.cgi?id=20141 – Will Moffat Commented Oct 14, 2010 at 18:12
  • Related: stackoverflow./questions/14146316/… – MvG Commented Apr 19, 2013 at 13:57
Add a ment  | 

2 Answers 2

Reset to default 8

First, if console is indeed undefined (as it is in browsers such as IE), you'll get an error. You should check it instead as a property of the global object, which is window in browsers. It's also a good idea in general to test a feature before using it, so I've added a test for the debug method.

Possibly the implementation of console.debug in Safari relies on its value of this being a reference to console, which will not be the case if you call it using _.log (this will instead be a reference to _). Having done a quick test, this does seem to be the case and the following fixes the problem:

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

I've been looking for a solution to this myself (this is how I found your question).

As Tim pointed out, webkit browsers (Safari, Chrome) rely on this being console in this case. Firefox, however, does not. So in FF you can reassign the function and preserve the line numbers (otherwise all logs look like they originated in the logging function, which is not very useful). The best way to check which browser you are is to do it and check the result. Here is how to check it (in Coffeescript):

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

Later, when you make the functions check assignSupported and act accordingly:

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

The lines:

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

might look a bit odd. This is because name is the loop variable and is lexically bound, meaning that the value at the time of execution will be used, which will always be the last level. It piles to this javascript (in case it's easier to read):

f = (function(n) {
  return (function() {
    return console[n].apply(console, arguments);
  });
})(name);

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744829221a4595982.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信