2013-11-08 6 views
3

У меня возникли некоторые проблемы в довольно большой части кода я пишу, и я варил к этому:Доступ «это» внутри объекта

var Thing = function(argument){ 
    this.property = argument; 
    this.obj = { 
     func: function(){ 
      return this; 
     } 
    }; 
    this.func = function(){ 
     return this; 
    }; 
}; 

Мне нужно получить доступ this.property внутри obj.func(). Тем не менее, значение this не то, что я ожидаю, что это будет:

> var thing = new Thing("value") 
> thing.func() 
Thing {property: "value", obj: Object, func: function} 
> thing.obj.func() 
Object {func: function} 

Когда я создаю экземпляр экземпляр под названием «вещь» и вызвать thing.func(), this имеет текущий экземпляр Thing, как это должно быть. Но когда я звоню thing.obj.func(), он держит значение thing.obj. Что происходит? Как получить доступ к этому значению?

ответ

4
var thing = new Thing('value') 
thing.obj.func() // this inside func will be the object before .func, which is thing.obj 

Одним из решений является связать функцию к объекту:

var Thing = function(argument){ 
    this.property = argument; 
    this.obj = { 
     func: function(){ 
      return this; 
     }.bind(this); // bind it to the current object 
    }; 
    this.func = function(){ 
     return this; 
    }; 
}; 

В качестве альтернативы можно использовать замыкание с собственной копией из this:

var Thing = function(argument){ 
    var that = this; 
    this.property = argument; 
    this.obj = { 
     func: function(){ 
      return that; 
     } 
    }; 
    this.func = function(){ 
     return this; 
    }; 
}; 
+0

Мне нравится решение '.bind (this)', потому что это означает, что большинство моего другого кода (есть намного больше, чем я включил в вопрос), может оставаться неизменным. –

+1

@ Dan Используйте 'bind' тщательно, он не поддерживается IE8 и ниже. – leaf

4

Объявите локальную переменную в конструкторе, и присвоить ему значение this:

var Thing = function(argument){ 
    var theThing = this; 

Вы можете использовать «theThing» для обозначения построенного объекта в этих функциях.

В вашем существующем коде, когда вы звоните thing.obj.func(), значение this в функции действительно будет this.obj. Это потому, что значение this определяется исходя из условий вызова функции. В этом случае ссылка на функцию («func») получается путем перемещения ее имени свойства на объект «obj». Таким образом, объект «obj» - это то, что this ссылок.

+0

Я предлагаю изменить имя переменной. 'self' зарезервирован в [браузерах Gecko] (https://developer.mozilla.org/en-US/docs/Web/API/Window.self) для объекта window. – matewka

+1

@matewka это не «зарезервировано»; он используется как псевдоним для 'window', но это совершенно законное имя переменной. Однако я изменю его; лично я бы не использовал его в любом случае :) – Pointy

+0

Вы правы - «зарезервировано» здесь не правильное слово. – matewka

1

Вот как работает this контекст javascript. Вы должны были бы хранить промежуточную ссылку на вещь:

var Thing = function(argument){ 
    var self = this; 
    this.property = argument; 
    this.obj = { 
     func: function(){ 
      return self; 
     } 
    }; 
    this.func = function(){ 
     return self; 
    }; 
}; 
+0

'this' не имеет ничего общего с областью видимости, это параметр контекста выполнения, который задается вызовом (или * bind *). – RobG

+0

@RobG Вы правы. – CodingIntrigue

0

this относится к объекту, который вл ns функция по умолчанию, в данном случае obj. Обходной путь:

thing.obj.func.call(thing); 
Смежные вопросы