Функция JavaScript сглаживание не работает
Я просто читала этот вопрос и хотел попробовать метод псевдонима, а не метод function-wrapper, но я не мог заставить его работать ни в Firefox 3, ни в 3.5beta4 или Google Chrome, как в их отладочных окнах, так и на тестовой веб-странице.
Firebug:
>>> window.myAlias = document.getElementById
function()
>>> myAlias('item1')
>>> window.myAlias('item1')
>>> document.getElementById('item1')
<div id="item1">
Если я помещаю его на веб-страницу, вызов myAlias дает мне эту ошибку:
uncaught exception: [Exception... "Illegal operation on WrappedNative prototype object" nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" location: "JS frame :: file:///[...snip...]/test.html :: <TOP_LEVEL> :: line 7" data: no]
Chrome (с > > > вставлен для ясности):
>>> window.myAlias = document.getElementById
function getElementById() { [native code] }
>>> window.myAlias('item1')
TypeError: Illegal invocation
>>> document.getElementById('item1')
<div id=?"item1">?
и на тестовой странице Я получаю тот же"незаконный вызов".
Я делаю что-то неправильно? Может кто-нибудь воспроизвести?
кроме того, как ни странно, я просто попытался, и он работает в IE8.
6 ответов
вы должны привязать этот метод к объекту document. Смотри:
>>> $ = document.getElementById
getElementById()
>>> $('bn_home')
[Exception... "Cannot modify properties of a WrappedNative" ... anonymous :: line 72 data: no]
>>> $.call(document, 'bn_home')
<body id="bn_home" onload="init();">
когда вы делаете простой псевдоним, функция вызывается на глобальном объекте, а не на объекте документа. Используйте метод под названием closures, чтобы исправить это:
function makeAlias(object, name) {
var fn = object ? object[name] : null;
if (typeof fn == 'undefined') return function () {}
return function () {
return fn.apply(object, arguments)
}
}
$ = makeAlias(document, 'getElementById');
>>> $('bn_home')
<body id="bn_home" onload="init();">
таким образом, вы не потеряете ссылку на исходный объект.
в 2012 году появился новый bind
метод из ES5, который позволяет нам делать это более причудливым образом:
>>> $ = document.getElementById.bind(document)
>>> $('bn_home')
<body id="bn_home" onload="init();">
я копнул глубоко, чтобы понять это конкретное поведение, и я думаю, что нашел хорошее объяснение.
прежде чем я доберусь до того, почему вы не можете псевдоним document.getElementById
, я попытаюсь объяснить, как работают функции/объекты JavaScript.
всякий раз, когда вы вызываете функцию JavaScript, интерпретатор JavaScript определяет область и передает ее функции.
рассмотрим следующую функцию:
function sum(a, b)
{
return a + b;
}
sum(10, 20); // returns 30;
эта функция объявлена в Область окна и при ее вызове значение this
внутри функции sum будет глобальный
Это короткий ответ.
следующее делает копию (ссылку на) функции. Проблема в том, что теперь функция находится на window
объект, когда он был разработан, чтобы жить на document
"объект".
window.myAlias = document.getElementById
варианты
- использовать обертку (уже упоминавшуюся Фабьеном Менагером)
-
или вы можете использовать два псевдонима.
window.d = document // A renamed reference to the object window.d.myAlias = window.d.getElementById
еще один короткий ответ, только для упаковки / сглаживания console.log
и аналогичные методы ведения журнала. Они все рассчитывают оказаться в console
контексте.
это можно использовать при оклеивании console.log
С некоторыми отступлениями, в случае, если вы или ваши пользователи столкнулись с проблемами, когда С помощью браузера, который не (всегда) поддерживает его. Это не полное решение этой проблемы, хотя, как это должно быть расширенные проверки и запасной вариант - ваш пробег может отличаться.
пример использование предупреждений
var warn = function(){ console.warn.apply(console, arguments); }
тогда используйте его как обычно
warn("I need to debug a number and an object", 9999, { "user" : "Joel" });
если вы предпочитаете видеть свои аргументы журнала, завернутые в массив (я делаю, большую часть времени), замените .apply(...)
С .call(...)
.
должны работать с console.log()
, console.debug()
, console.info()
, console.warn()
, console.error()
. См. также console
на MDN.
в дополнение к другим отличным ответам, есть простой метод jQuery $.прокси.
Вы можете псевдоним такой:
myAlias = $.proxy(document, 'getElementById');
или
myAlias = $.proxy(document.getElementById, document);
вы на самом деле не могу "чистый псевдоним" функция на предопределенном объекте. Поэтому ближе всего к сглаживанию вы можете получить без обертывания, оставаясь в одном объекте:
>>> document.s = document.getElementById;
>>> document.s('myid');
<div id="myid">