简体   繁体   中英

Using native code functions as JavaScript objects in WebKit

I'm unable to use native code functions as JavaScript objects in WebKit-based browsers. Is it impossible to alias these functions directly?

This is easiest to explain by example, so here is what I am running in the Developer Tools console:

console.warn;
// Outputs:
// function warn() {
//     [native code]
// }

console.warn("console.warn");
// Outputs: "console.warn"

var _c = console;
_c.warn("_c.warn");
// Outputs: "_c.warn"

var _w = console.warn;
_w("_w");
// Outputs: "TypeError: Type error" on Safari/WebKit (Mac)
// Outputs: "TypeError: Illegal invocation" on Chrome (Mac)

var _w2 = function () { console.warn.apply(console, arguments); }
_w2("_w2");
// Outputs: "w2"

This issue came up as I tried to use jQuery Lint in Safari; it uses the following approach to prevent breakage if window.console does not exist:

_console = {
    warn: window.console && console.warn || function(){},
    ...
}

_console.warn("some error");

Here's my temporary workaround:

if((jQuery.browser.safari || jQuery.browser.webkit) && window.console) {
    jQuery.LINT.level = 3;
    jQuery.LINT.console = {
        warn: function() { console.warn.apply(console, arguments); },
        group: function() { console.group.apply(console, arguments); },
        groupEnd: function() { console.groupEnd(); },
        groupCollapsed: function() { console.group.apply(console, arguments); },
        log: function() { console.log.apply(console, arguments); }
    }
}

You can't alias any methods in JavaScript, native or not, WebKit or not.

When you say var _w = console.warn; , you are stripping warn away from its owner object console and treating it as a standalone function. When you call it, it gets no this reference to the console , so it fails to work.

You may find this unusual from how bound methods work in other languages, but that's just how JavaScript method calls are designed: the this reference is passed to a function based solely on what owner is in owner.method() (or owner['method']() ). If the function is called alone without an owner, this is set to the window object and the method will most likely fall over.

To get around this and pass in a proper this , you must either use method.call (or method.apply ) explicitly as described by @slebetman, or make your own bound function using a closure like var _w= function() { console.warn.apply(console, arguments) }; or, in ECMAScript Fifth Edition, method.bind(owner) .

That should be:

console.warn.apply(console,arguments);

The first parameter to apply is the value of this to pass into the warn method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM