2012-04-26 2 views
0

У меня есть [казалось бы] тривиальный шаблон dust.js. Объект контекста, который я использую для визуализации шаблона, содержит обработчик, который ссылается на другой элемент в контексте объекта. Я также включаю обработчик toString, который также ссылается на другой элемент в объекте context.dust.js теряют «этот» контекст в обработчиках?

Шаблон:

{error} 
<pre> 
{#error.getStackTrace} 
{.}{~n} 
{/error.getStackTrace} 
</pre> 

Контекст:

{ 
    error: { 
    st: ['a','b','c'], 
    msg: 'This is an error message', 
    getStackTrace: function() { 
     return this.st; 
    }, 
    toString: function() { 
     return this.msg; 
    } 
    } 
} 

Вынесено:

This is an error message<pre></pre> 

Если я ссылаться {#error.st} напрямую, он делает правильно:

This is an error message<pre>a 
b 
c 
</pre> 

Если я проверяю «это» внутри обработчика getStackTrace(), он указывает на DOMWindow. Интересно, однако, что вызов функции toString() неявно, она правильно определена. Если я явно вызываю toString() {error.toString}, то область возвращается к DOMWindow.

Единственная причина, по которой это проблема, (почему я не могу напрямую получить доступ к error.st), потому что массив st фактически хранится в свойстве Qooxdoo, и у меня есть только доступ к сгенерированному getter. Вышеприведенный пример имитирует фактический объект как можно проще.

Это ошибка в dust.js? Потеряет ли он правильную область в обработчиках? Или я пропущу что-то в файле dust.js, чтобы сохранить область видимости?

ответ

0

вы могли бы использовать его таким образом:

{ 
error: { 
    st: 'a,b,d', 
    msg: 'This is an error message', 
    getStackTrace: function (chunk, context) { 
    return context.current().error.st; 
    }, 
    toString: function() { 
    return this.msg; 
    } 
} 
} 
+0

Это правильное решение, но это не обязательно решает мою проблему. Я надеялся, что объект модели и шаблон/контекст будут полностью разделены. Спасибо, jairo! – schlomie

+0

Несмотря на то, что официальные [оригинальные] документы ошибочны: «Пыли все равно, как создаются ваши эталонные объекты. Например, вы можете протолкнуть прототипированные объекты в стек. Система оставляет это ключевое слово неповрежденным при вызове функций обработчика на ваши объекты. " - под заголовком «Контексты» (http: //akdubya.github.com/dustjs /) – schlomie

0

это является Javascript не всегда очевидна, особенно, когда вы возвращаете функции.

Когда Пыль разрешает ссылки, такие как {error.st}, который является функцией. Он вызывает эту функцию, но она не устанавливает для нее возможности; поэтому по умолчанию используется глобальная область действия, которая в вашем браузере равна window.

Посмотрите на этой линии: https://github.com/akdubya/dustjs/blob/master/lib/dust.js#L319

Вот что происходит Сорта:

var current_context = { 
    st: 'a,b,d', 
    msg: 'This is an error message', 
    getStackTrace: function (chunk, context) { 
    return error.st; 
    }, 
    toString: function() { 
    return this.msg; 
    } 
} 
current_context.st(); // outputs correctly 

var elem = current_context.st; // here is your reference {.} 
elem(); // Dust tries to resolve your reference but it doesn't set the scope 
elem.call(current_context); // if we pass the scope you'll get what you want. 

Является ли это ошибка в пыли? Вероятно, нет, поскольку у вас есть контекст через context.current().

Имеет смысл для this, чтобы указать на window. Нет, но когда вы используете Dust на стороне сервера, я думаю, мы будем лучше использовать для this.

+0

Что касается «Он вызывает эту функцию, но не устанавливает ее для нее, поэтому по умолчанию она соответствует глобальной области действия, которая в вашем браузере является окном» ... Это противоречит заявлению о документы, что «это» остается нетронутым. Это изнутри прототипа, это всегда должно ссылаться на прототипированный объект. elem.call() вернется в глобальную область, да, поэтому вы можете перейти в контекст, используя elem.call (context.) Почему бы не elem.apply (context, [...])? Это сохранит правильную область действия. – schlomie

+0

рассмотрим следующее: var obj = {a: 'abc', method: function() {return this.a; }}; var b = obj.method; obj.method b.call();/* undefined */b.apply (obj, []);/* 'abc' */Это правильный способ выполнить закрытие и сохранить область. – schlomie

+0

'Пыль все равно, как строятся ваши эталонные объекты. Например, вы можете протолкнуть прототипированные объекты в стек. Система оставляет это ключевое слово неповрежденным при вызове функций обработчика на ваших объектах. « – jimmyhchan

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

  • Нет связанных вопросов^_^