Using native code functions as JavaScript objects

2019-04-11 02:08发布

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); }
    }
}

2条回答
我欲成王,谁敢阻挡
2楼-- · 2019-04-11 02:37

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).

查看更多
趁早两清
3楼-- · 2019-04-11 02:40

That should be:

console.warn.apply(console,arguments);

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

查看更多
登录 后发表回答