Обновить
Для ясности: @FelixKing: Да, я ожидал, что this
по-прежнему будет неопределенным при вызове window.foo()
, и вот почему: поскольку в JavaScript:
function foo()
{
console.log('I am a function');
}
Это (почти) то же самое, что и:
var foo = function()
{
console.log('I am a function');
}
и foo === window.foo
оценивается как true, я ожидаю, что они оба будут вести себя одинаково. Если функции являются переменными, а JS возвращается к глобальному объекту (внутри функции x переменная не объявляется, но вы ее используете, JS пузырится вверх по всем областям, вплоть до глобального объекта, пока он находит рассматриваемую переменную или создает ее на глобальном уровне), не имеет значения, указывает ли объект window
заранее или нет. Тем не менее, когда вы это делаете, поведение меняется, чего я не ожидал.
У меня есть интуитивное чувство, почему это так (я определяю методы, а не переменные ), но опять же, для глобальных объектов между ними очень мало различий. var c = 'Variable'; console.log(window.c === c);
регистрирует true и т. д... но я хотел бы знать, в чем разница на самом деле и как она работает (на всех уровнях).
Я готов зайти так далеко, что смирюсь с тем, что foo.apply(this,[]);
или foo.apply(window,[]);
позволяют заставить this
указывать на глобальный объект, но не window.foo();
. Если strict существует для защиты глобального объекта, я бы сказал, что это оставляет черный ход широко открытым. Иногда я вызываю функции, например, в зависимости от значения переменной. Для этого я использую window[myVar]();
, строгий или нет, это означает, что this
будет указывать на глобальный объект, тогда как если я вызываю функцию напрямую, это не так. Это, на мой взгляд, несоответствие.
Я столкнулся со странным поведением ключевого слова this
в строгом режиме. Не поймите меня неправильно, я знаю, что this
— это undefined в строгих функциях. Что меня сбивает с толку, так это то, что this
можно принудительно указать на глобальный объект (или любой другой объект, если на то пошло), эффективно подрывая систему безопасности, обеспечиваемую строгим режимом. Это имеет и другие последствия. Рассмотрим этот код:
'use strict';//using strict everywhere
(function(Global)
{
var closureObject = {};
Global.foo = function()
{
closureObject.setIn = closureObject.setIn || 'Set in foo';
console.log(this);
console.log(this === Global);
bar();
bar.apply(this);
return (this !== Global ? this : undefined);
};
Global.bar = function()
{
closureObject.setIn = closureObject.setIn || 'set in bar';
console.log(this);
return (this !== Global ? this : undefined);
};
})(this);
var undef = (Math.ceil(Math.random()*10)%2 ? foo() : bar());
foo();//undefined --- false --- undefined --- undefined
window.foo();//Window --- true --- undefined --- window
foo.apply(this,[]);//same as window.foo
То же самое относится и к пользовательским объектам:
function Foo(n)
{
this.name = n;
}
Foo.prototype.func = foo;//or window.foo
//other objects:
var d = new Date();
foo.apply(d,[]);//Date --- false --- undefined --- date
Это, на мой взгляд, возможный источник хаков и ловушек. Более того: довольно сложно определить, откуда исходит вызов: если foo()
был вызван из глобального объекта (window.foo();
), этот контекст, конечно, не передается bar
, если только bar
не вызывается с использованием bar.apply(this,[]);
.
Причина, по которой мне может понадобиться простой, безопасный и надежный способ определения контекста вызывающей стороны, проста: я использую замыкание, чтобы избежать этих надоедливых глобальных переменных, но в то же время я настраиваю пару функции, которые служат обработчиками событий.
Я знаю, что не использовать строгий режим или установить глобальный режим — это легко исправить, но строгий режим никуда не денется, и мне нравится то, что он привносит на вечеринку (ну, большую часть). Я твердо верю, что JS будет развиваться именно так, и мне бы очень не хотелось плакать из-за собственного неработающего кода из-за того, что я не хочу возиться с strict
. Возможно, это произойдет не так скоро, но я просто хочу поддерживать свои знания в актуальном состоянии.
Я прочитал страницы MDN на strict
, а также сообщение в блоге Джона Резига, я посмотрел довольно много видео DC и прочитал много его статей, и я не нашел окончательного объяснения поведения, которое я описал выше. . Я не читал весь стандарт ECMAScript (Боже, это настолько сухо, что может осушить пустыню Сахара), но, возможно, кто-то здесь может указать мне правильное направление, чтобы помочь мне лучше понять это.
this
тоже будетundefined
, если вы позвонитеwindow.foo()
? - person Felix Kling   schedule 03.09.2012this
можно с радостью упомянуть, когда он не в функциях (в JS нетmain()
). И как я вижу, это именно то, что здесь происходит. - person raina77ow   schedule 03.09.2012this
не указывает на undefined в строгом режиме, чтобы избежать установки глобальных переменных, когда они не должны (например, конструкторы без ключевого словаnew
). Я как бы ожидал, чтоwindow.foo()
не изменит это, если весь смысл не в установке глобальных переменных, то глобальный контекст должен быть закрыт, не так ли? Я имею в виду, что согласованность это суть строгого режима, верно? зачем тогда включать хакерские обходные пути? - person Elias Van Ootegem   schedule 03.09.2012object.method
, вы напрямую определяетеthis
. Если бы это привело кundefined
, это было бы серьезной дырой в прототипном наследии WRT. - person gray state is coming   schedule 03.09.2012window.foo();
для вызова своей функции, устанавливаяthis
для указания на глобальный объект, чего на самом деле не должно быть. На мой взгляд, открытие глобального объекта должно быть возможным, но только с вызовом функции, который показывает определенное намерение (например,strictFunction.call(window);
или что-то в этом роде. - person Elias Van Ootegem   schedule 03.09.2012