У меня вопрос о том, как обрабатывается указатель «this» в сценарии вложенной функции.
Скажем, я вставил следующий пример кода на веб-страницу. Я получаю сообщение об ошибке при вызове вложенной функции «doSomeEffects ()». Я проверил в Firebug, и это показывает, что когда я нахожусь во вложенной функции, указатель this фактически указывает на глобальный объект «окно», чего я не ожидал. Я не должен понимать что-то правильно, потому что я думал, что, поскольку я объявил вложенную функцию внутри функции объекта, она должна иметь "локальную" область видимости по отношению к функции (т.е. указатель "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();
javascript
function
nested
this
JoJoeDad
источник
источник
this
относится к объекту, для которого функция вызывается.var self = this;
а затем ссылатьсяself
на внутреннюю функцию через закрытие.doSomeEffects
не связан с каким-либо obj в частности, поэтомуthis
предполагается, что это окно, мать всех элементов.Ответы:
В JavaScript
this
объект действительно основан на том, как вы выполняете вызовы функций.В общем, есть три способа настроить
this
объект:someThing.someFunction(arg1, arg2, argN)
someFunction.call(someThing, arg1, arg2, argN)
someFunction.apply(someThing, [arg1, arg2, argN])
Во всех приведенных выше примерах
this
объектом будетsomeThing
. Вызов функции без ведущего родительского объекта обычно дает вам глобальный объект, который в большинстве браузеров означаетwindow
объект.источник
this.doSomeEffects();
на ваш ответ, но он все равно не работает. Зачем?this
вthis.doSomeEffects()
точках кstd_obj
. Как объяснено в ответе выше, если функция не имеет ссылки на объект, онаthis
должна быть объектом окна.Поскольку это один из самых популярных вопросов в своем роде, позвольте мне добавить после всех этих лет решение 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") { } }; ... } };
источник
this
не является частью области закрытия, его можно рассматривать как дополнительный параметр функции, привязанной к месту вызова. Если метод не вызывается как метод, глобальный объект передается какthis
. В браузере глобальный объект идентиченwindow
. Например, рассмотрим следующую функцию,function someFunction() { }
и следующий объект,
var obj = { someFunction: someFunction };
Если вы вызываете функцию с использованием синтаксиса метода, например,
то
this
обязательноobj
.Если вы вызываете someFunction () напрямую, например,
then
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(); }
источник
Есть разница между переменными вложения и «это». «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 ()», вызывается явно, это означает, что контекст или «это» функции - это окно. если «doSomeEffects» был методом прототипа, например this.doSomeEffects, скажем, «myObject», то myObject.doSomeEffects () приведет к тому, что «this» будет «myObject».
источник
_this.name = myFirstObject this.name = mySecondObject
Чтобы понять этот вопрос, попробуйте получить вывод для следующего фрагмента
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
Во внешней функции this и self относятся к myObject, и поэтому оба могут правильно ссылаться на foo и обращаться к нему.
Однако во внутренней функции это больше не относится к myObject. В результате this.foo не определен во внутренней функции, тогда как ссылка на локальную переменную self остается в области видимости и доступна там. (До ECMA 5 this во внутренней функции будет относиться к глобальному объекту окна; тогда как в ECMA 5 this во внутренней функции будет неопределенным.)
источник
this
ссылается на объект окна (в среде браузера) или ГЛОБАЛЬНЫЙ объект (в среде node.js)this
больше не относится к окнуКак объяснил Кайл, вы можете использовать
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
источник
Я также получил предупреждение " Возможно недействительный доступ по ссылке к полю класса через это "
class MyListItem { constructor(labelPrm) { this._flagActive = false; this._myLabel = labelPrm; labelPrm.addEventListener('click', ()=>{ this.onDropdownListsElementClick();}, false); } get myLabel() { return this._myLabel } get flagActive(){ return this._flagActive; } onDropdownListsElementClick(){console.log("Now'this'refers to the MyListItem itself")}}//end of the class
источник
Поскольку об этом не упоминалось, я упомяну, что использование
.bind()
- это решение -doSomeEffects=doSomeEffect.bind(this); doSomeEffects(); } }; std_obj.displayMe();
Вот более простой пример -
bad = { name:'NAME', z : function() { function x() { console.log(this.name); }; x() } }; bad.z() // prints 'undefined' good = { name:'NAME', z : function() { function x() { console.log(this.name); }; x=x.bind(this); x(); } }; good.z() // prints 'NAME'
Верно, что использование стрелочной функции
=>
выглядит более гладко и легко для программиста. Однако следует иметь в виду, что лексическая область видимости, вероятно, потребует больше работы с точки зрения обработки и памяти для настройки и поддержки этой лексической области по сравнению с простым связыванием функцииthis
с указателем через.bind()
.Частично преимущества разработки классов на JS заключались в предоставлении метода, позволяющего сделать их
this
более надежным и доступным, чтобы отказаться от функционального программирования и лексических областей видимости и, таким образом, сократить накладные расходы.Из MDN
источник