Javascript "this" указатель внутри вложенной функции
У меня вопрос о том, как обработчик "this" обрабатывается в сценарии вложенных функций.
Скажем, я вставляю этот следующий пример кода в веб-страницу. Я получаю сообщение об ошибке, когда я вызываю вложенную функцию "doSomeEffects()". Я проверил в Firebug, и это указывает, что когда я нахожусь в этой вложенной функции, указатель "this" фактически указывает на глобальный объект "window", чего я не ожидал. Я не должен правильно понимать что-то, потому что я думал, что, поскольку я объявил вложенную функцию внутри функции объекта, она должна иметь "локальную" область действия по отношению к функции (т.е. Указатель "this" будет ссылаться на сам объект, например как это в моем первом выражении "если" ).
Любые указатели (не предназначенные для каламбуров) будут оценены.
var std_obj = {
options : { rows: 0, cols: 0 },
activeEffect : "none",
displayMe : function() {
// the 'this' pointer is referring to the std_obj
if (this.activeEffect=="fade") { }
var doSomeEffects = function() {
// the 'this' pointer is referring to the window obj, why?
if (this.activeEffect=="fade") { }
}
doSomeEffects();
}
};
std_obj.displayMe();
Ответы
Ответ 1
В JavaScript объект this
действительно основан на том, как вы выполняете вызовы функций.
Как правило, существует три способа установки объекта this
:
-
someThing.someFunction(arg1, arg2, argN)
-
someFunction.call(someThing, arg1, arg2, argN)
-
someFunction.apply(someThing, [arg1, arg2, argN])
Во всех приведенных выше примерах объект this
будет someThing
.
Вызов функции без ведущего родительского объекта обычно будет вам глобальным объектом, который в большинстве браузеров означает объект window
.
Ответ 2
this
не является частью области закрытия, его можно рассматривать как дополнительный параметр для функции, связанной с сайтом вызова. Если метод не вызывается как метод, глобальный объект передается как this
. В браузере глобальный объект идентичен window
. Например, рассмотрим следующую функцию:
function someFunction() {
}
и следующий объект
var obj = { someFunction: someFunction };
Если вы вызываете функцию с использованием синтаксиса метода, например,
obj.someFunciton();
то this
привязан к obj
.
Если вы вызываете someFunction() напрямую, например
someFunction();
то this
привязан к глобальному объекту, то есть window
.
Наиболее распространенная работа заключается в том, чтобы зафиксировать это в закрытии, например,
displayMe : function() {
// the 'this' pointer is referring to the std_obj
if (this.activeEffect=="fade") { }
var that = this;
var doSomeEffects = function() {
// the 'this' pointer is referring to global
// that, however, refers to the outscope this
if (that.activeEffect=="fade") { }
}
doSomeEffects();
}
Ответ 3
Поскольку это, по-видимому, относится к числу наиболее распространенных вопросов такого рода, позвольте мне добавить все эти годы решение ES6 с использованием функций стрелок:
var std_obj = {
...
displayMe() {
...
var doSomeEffects = () => {
^^^^^^^ ARROW FUNCTION
// In an arrow function, the 'this' pointer is interpreted lexically,
// so it will refer to the object as desired.
if (this.activeEffect=="fade") { }
};
...
}
};
Ответ 4
Существует разница между переменными окружения и "this". "this" фактически определяется вызовом функции, в то время как явные переменные остаются неповрежденными внутри блока объявления функции, известного как оболочка. См. Пример ниже:
function myFirstObject(){
var _this = this;
this.name = "myFirstObject";
this.getName = function(){
console.log("_this.name = " + _this.name + " this.name = " + this.name);
}
}
function mySecondObject(){
var _this = this;
this.name = "mySecondObject";
var firstObject = new myFirstObject();
this.getName = firstObject.getName
}
var secondObject = new mySecondObject();
secondObject.getName();
вы можете попробовать:
http://jsfiddle.net/kSTBy/
Что происходит в вашей функции - "doSomeEffects()", вызывается явно, это означает, что контекст или "this" функции - это окно. если "doSomeEffects" был прототипом, например. this.doSomeEffects on say "myObject", тогда myObject.doSomeEffects() вызовет "this" как "myObject".
Ответ 5
Чтобы понять этот вопрос, попробуйте получить вывод для следующего фрагмента
var myObject = {
foo: "bar",
func: function() {
var self = this;
console.log("outer func: this.foo = " + this.foo);
console.log("outer func: self.foo = " + self.foo);
(function() {
console.log("inner func: this.foo = " + this.foo);
console.log("inner func: self.foo = " + self.foo);
}());
}
};
myObject.func();
Приведенный выше код выведет на консоль следующее:
outer func: this.foo = bar
outer func: self.foo = bar
inner func: this.foo = undefined
inner func: self.foo = bar
Во внешней функции, как это, так и самостоятельно ссылаются на myObject, и поэтому оба могут правильно ссылаться и получать доступ к foo.
Во внутренней функции это больше не относится к myObject. В результате this.foo является undefined во внутренней функции, тогда как ссылка на локальную переменную self остается в области видимости и доступна там. (До ECMA 5 это во внутренней функции относится к глобальному объекту окна, тогда как по ECMA 5 это во внутренней функции будет undefined.)
Ответ 6
Как объяснил Кайл, вы можете использовать call
или apply
для указания this
внутри функции:
Вот эта концепция, применяемая к вашему коду:
var std_obj = {
options: {
rows: 0,
cols: 0
},
activeEffect: "none",
displayMe: function() {
// the 'this' pointer is referring to the std_obj
if (this.activeEffect == "fade") {}
var doSomeEffects = function() {
// the 'this' pointer is referring to the window obj, why?
if (this.activeEffect == "fade") {}
}
doSomeEffects.apply(this,[]);
}
};
std_obj.displayMe();
JsFiddle