Этот указатель из внутренней функции - PullRequest
5 голосов
/ 15 февраля 2011

У меня есть компоненты JavaScript, которые имеют следующую архитектуру:

var MyComponent = function(params)
{
    setup(params);


    this.doSomething()
    {
        // doing something
    };

    function setup(params)
    {
        // Setup

        // Interaction logic
        var _this = this; // "this" points to DOMWindow, not to created object
        $(".some-element").click(function(){
            _this.doSomething(); // it craches here, because of above
        });
    }
};

Когда что-то, управляемое логикой взаимодействия, происходит, иногда я должен перенаправлять выполнение "публичным" методам компонента.

В этой ситуации у меня проблема с указателем "this".

Пример кода демонстрирует это:

var Item = function()
{
    this.say = function()
    {
        alert("hello");
    };
    this.sayInternal = function()
    {
        _sayInternal();
    };
    function _sayInternal()
    {
        this.say();
    };
};

Чтобы проверить это,

  • Создатьобъект:

var o = new Item();

  • Это прекрасно работает:

o.say(); // alerts "hello"

  • Этосбои:

o.sayInternal();

Я получаю сообщение об ошибке:

TypeError: Результат выражения 'this.say' [undefined] не являетсяfunction.

Я думаю, такое поведение имеет место, потому что функция _sayInternal () объявлена ​​ (и не присвоена объекту, как "this.say = function ()").Таким образом, он используется всеми созданными объектами и действует как статическая функция в C ++.

Это правда?

1 Ответ

3 голосов
/ 15 февраля 2011

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

this всегда ссылается на контекст, в котором вызывается функция. Если вы вызываете ее как func(), то this ссылается на глобальный объект (которыйwindow в браузере).Если вы установите функцию как свойство объекта и вызовете ее с помощью obj.func(), тогда this будет ссылаться на obj.

Если вы назначите «связанную» функцию переменной и вызовете ее:

var method = obj.func;
method();

, тогда this снова будет ссылаться на глобальный объект.В JavaScript функции похожи на любое другое значение, они не имеют особого отношения к объекту, которому они назначены.


Вы можете явно установить контекст с помощью call или apply:

var MyComponent = function(params)
{
    setup.call(this, params); // <- using `call`

    this.doSomething()
    {
        // doing something
    };

    function setup(params)
    {
        // Setup  
        // Interaction logic
        var _this = this; // "this" to new  created object
        $(".some-element").click(function(){
            _this.doSomething();
        });
    }
};

или в другом примере:

var Item = function()
{
    this.say = function()
    {
        alert("hello");
    };
    this.sayInternal = function()
    {
        _sayInternal.call(this);
    };
    function _sayInternal()
    {
        this.say();
    };
};

Тем не менее, этот подход для назначения функций объектамне хорошо, потому что каждый экземпляр будет иметь свою собственную функцию this.sayInternal.Поэтому для приведенного выше кода Item каждое создание экземпляра также включает создание трех функций, что является пустой тратой памяти.

Использование наследования прототипа было бы лучшим способом:

var Item = function() {
};

Item.prototype = (function() {
    function _sayInternal() {
        this.say();
    };

    return {
        say: function() {
            alert("hello");
        },
        sayInternal: function(){
            _sayInternal.call(this);
        }
    }
}());

Таким образом, _sayInternal создается только один раз , и все экземпляры наследуют (ссылаются) на прототип, поэтому say и sayInternal также существуют только один раз.«Трюк» с функцией немедленное делает _sayInternal доступным только для say и sayInternal.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...