2013-05-02 4 views
0

У меня есть следующий код для целей JS-обучения:JavaScript - как сохранить состояние «это» правильно

function A() { 
    var self = this; 

    this.test1 = function() { 
     console.log("A_test1"); 
     B().test2(); 
     return self; 
    } 

    this.problem = function() { 
     console.log("I'm never called"); 
    } 

    return self; 
} 

function B() { 
    var self = this; 

    this.test2 = function() { 
     console.log("B_test2"); 
     return self; 
    } 

    this.problem = function() { 
     console.log("I'm a headach and overwrite others in my free time"); 
    } 

    return self; 
} 

/* 
* This is our "main" function like in C 
*/ 
$(function(){ 
    A().test1().problem(); 
}); 

Я отлаженный код с Firebug. Давайте рассмотрим нижеприведенную строку из «основной» функции: A(). Test1(). Problem();

1) A()
«Ключевое слово„это“не является функцией (класс) объекта. Это всегда„окно“объект, который распространяется построчно в время выполнения с помощью свойств/методов текущего объекта (в нашем случае: объект функции A). Итак, когда мы доходим до конца A() (т.е. «return self»), содержимое этого «этого» объекта следующее:

  • все свойства/методы "окна" объект
  • test1() и Проблема.() Методы A

2) А() test1() метод
test1() имеет линию "B() test2();". Так она называет в следующем B()

2,1) B()
Когда мы достигаем конца B() (т.е. Самовозврат), «это» содержание объекта заключается в следующем:

  • всех свойства/методы «окно» объект
  • test1() метод
    [задача() метод А теряется, потому что она перезаписывается задачами() из B]
  • test2() и проблема() методы B

2.2) B(). test2()
Это работает, как ожидалось, и это нормально. Итак, мы финишируем с помощью A(). Test1().

3) A(). Test1(). Problem();
И это вызывает метод проблемы B(), хотя я хочу вызвать проблему A() здесь.

Итак, каков правильный способ сохранения онлайн-состояния «этого» объекта? (Понятно, что «я» вообще не имеет никакого эффекта, поскольку это ссылка (например, на C) на «этот» объект.)

Я мог бы клонировать состояние этого «объекта» в начале каждый конструктор, то есть:
вместо

var self = this; 

как об этом

var self = this.clone(); 

Но я не уверен, если это хорошая идея.Причина клонирования состояния «этого» для каждого вновь созданного объекта могла бы убить память в большой структуре, не так ли?

Я уверен, что я не первый человек, столкнувшийся с этой проблемой. Мой поисковик Google дал мне немного. Так снова, каков правильный способ спасти «это»? Как я могу позволить проблеме A() вызывать в этом примере вместо задачи B()?

+0

необходимо использовать конструктор 'A', то есть' var a = new A() ', тогда' this' укажет на новый объект вместо 'window' –

+0

@ArunPJohny: Отправьте это как ответ. – icktoofay

+0

@icktoofay done –

ответ

2

вам нужно использовать A как конструктор т.е. var a = new A(), то это будет указывать на новый объект вместо window

+0

Должен ли я всегда вызывать функцию, чем с помощью «нового» ключевого слова? Есть ли побочные эффекты? (например, создание дублирующих объектов функции) –

+1

@ moller1111 no, если вы работаете с объектами, так как в этом случае вы должны использовать 'new' –

+0

спасибо. я отвечу на ваш ответ, потому что вы были первыми, и вы ответили на дополнительный вопрос, как я этого хотел. Для всех, кто читает этот комментарий: см. Другие сообщения для «self» tip «Umur Kontacı» и рекомендуемую ссылку на книгу «jdigital» ниже. –

1

Если вы звоните new на вашей функции, то this будет, по сути, быть экземпляром объекта, а не окно ... так ...

function Foo(){ 
    this.whatAmI = function(){ 
     console.log("I am " + this); 
    } 
} 


var bar = new Foo(); 
bar.whatAmI(); 
2
var x = new A(); 

new ключевого слова в JavaScript имеет функцию, которая устанавливает this переменные новый instanc е. Если вы используете var x= A();, то this в A будет window (то есть глобальный контекст).

Для этих простых настроек вам не нужно использовать var self = this;, пока вам не понадобится обратный вызов, но для удобства вы можете сделать это без каких-либо побочных эффектов. Установка значения переменной для этого, чтобы сделать ее последовательной, совершенно правильная и очень распространенная, имя переменной обычно that вместо self, но это просто сахар.

+0

'Function.prototype.bind' иногда также может использоваться. – icktoofay

+0

thx для подсказки обратного вызова –

+0

@icktoofay 'bind' находится в ECMAScript 5; поэтому он недоступен в старых браузерах. Кстати, как вы можете привязать его к новому объекту (т. Е. Реплицировать новый)? –

1

Другие ответы («use new») являются правильными.

Я думаю, вам понравятся работы Джона Ресига. Взгляните на его книгу (Secrets of the Javascript Ninja) или посетите the interactive Javascript tutorial на своем веб-сайте.

+0

Должен ли я всегда вызывать функцию, чем с помощью «нового» ключевого слова? Есть ли побочные эффекты? (например, создание объектов дублирующих функций) –

+0

Нет, не стоит. Вот почему я предложил посмотреть учебные материалы, чтобы вы могли лучше понять, как это работает. – jdigital

Смежные вопросы