2016-01-21 2 views
2

Для методов prototype существует ли безопасный способ гарантировать, что this всегда является самим объектом (вне проверки instanceof и ошибкой).Обеспечьте «этот» контекст в прототипном методе

var Dialog = function() {}; 
Dialog.prototype.open = function() { 
    var open = this; 
    // how do ensure "this" is always the Dialog 
    console.log(open); 
}; 

С помощью этого кода любой пользователь может ошибочно «принудить» контекст быть неверным. Например:

var pointer = new Dialog().open; 
pointer(); // "this" would become Window 

Я пытаюсь найти способ справиться с этой внутренне так, что я не должен выдавать ошибку или полагаться на пользователя, чтобы всегда делать правильные вещи.

Пользователь всегда может вызывать pointer.call(dialog), но это означает, что для диалога требуется отдельный указатель, и это хороший пример бремени для пользователя, а не для меня, автора.

+1

Вы намерены иметь несколько экземпляров диалогового окна? Вы хотите разрешить пользователю использовать экземпляр «Dialog» напрямую? ('var d = new Dialog(); d.open();') –

+2

Это не то, о чем ваш класс/библиотека действительно беспокоиться. Если пользователь неправильно вызывает/вызывает метод, это их проблема. Они должны правильно использовать язык, чтобы все функционировало правильно. –

+0

Да, может быть несколько экземпляров, и я разрешу пользователю повторно использовать экземпляр. – helion3

ответ

1

Это действительно шумный и развалин, который дает вам прирост производительности с прототипическим наследованием, но вы можете явно привязать каждую из функций внутри конструктора.

function log(obj) { 
 
    document.querySelector('pre').innerText += obj.toString() + '\n'; 
 
} 
 

 
function Dialog() { 
 
    this.open = this.open.bind(this); 
 
} 
 
Dialog.prototype.open = function() { 
 
    log(this); 
 
}; 
 
Dialog.prototype.toString = function() { 
 
    return '[object Dialog]'; 
 
}; 
 

 
var d = new Dialog(); 
 
d.open(); 
 
var open = d.open; 
 
open();
<pre></pre>

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

1

Вы не можете предотвратить это с помощью прототипирования. bind предложение Майка C действительно делать дело, но это в основном очень сложный/дорогой способ использовать шаблон декоратора, который действительно решает проблему рамочный:

function Dialog() { 
    var dialog = this; 

    dialog.open = function() { 
     console.log(dialog, this); 
    }; 
} 

var d = new Dialog(); 
d.open(); 

var open = d.open(); 
open(); 

Имейте в виду, что этот подход гораздо меньше памяти, чем пример prototype в вашем вопросе, поэтому никогда не используйте его, если у вас много примеров.

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