Использование функций собственного кода в качестве объектов JavaScript в WebKit - PullRequest
3 голосов
/ 19 января 2010

Я не могу использовать функции собственного кода в качестве объектов JavaScript в браузерах на основе WebKit. Разве нельзя псевдоним этих функций напрямую?

Это проще всего объяснить на примере, поэтому вот что я запускаю в консоли инструментов разработчика:

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"

Эта проблема возникла, когда я пытался использовать jQuery Lint в Safari; он использует следующий подход для предотвращения поломки, если window.console не существует:

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

_console.warn("some error");

Вот мой временный обходной путь:

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 ]

7 голосов
/ 19 января 2010

Вы не можете использовать псевдоним любой метод в JavaScript, нативный или нет, WebKit или нет.

Когда вы говорите var _w = console.warn;, вы удаляете warn из объекта-владельца console и рассматриваете его как отдельную функцию. Когда вы вызываете его, он не получает this ссылку на console, поэтому он не работает.

Это может показаться необычным из-за того, что связанные методы работают в других языках, но именно так устроены вызовы методов JavaScript: ссылка this передается функции, основываясь исключительно на том, что owner находится в owner.method() ( или owner['method']()). Если функция вызывается одна без владельца, this устанавливается для объекта window, и метод, скорее всего, будет сброшен.

Чтобы обойти это и передать правильный this, вы должны либо явно использовать method.call (или method.apply), как описано в @slebetman, либо создать собственную связанную функцию, используя замыкание, например var _w= function() { console.warn.apply(console, arguments) }; или в пятом издании ECMAScript method.bind(owner).

2 голосов
/ 19 января 2010

Это должно быть:

console.warn.apply(console,arguments);

Первый применяемый параметр - это значение this для передачи в метод warn.

...