Javascript и эта ошибка.В зависимости от того, как вызывается функция - PullRequest
1 голос
/ 21 февраля 2012

Так что это сложно.При непосредственном вызове метода это относится к содержащему объекту, в то время как при вызове преобразования строки это относится к «окну» (я верю, что я все еще могу быть совершенно неправым).

Может ли кто-нибудь объяснить мне это?

Что произойдет, это ошибка javascript ПОСЛЕ первого оператора оповещения (это означает, что прямой вызов работал нормально, как было определено _this)

/**
 *  converts a string to a function
 */
function stStringToFunction(string) {
    var fnList = string.split(".");
    var currentFn = window;
    var nextFn;
    while(currentFn !== undefined && (nextFn = fnList.shift())) {
        currentFn = currentFn[nextFn];  
    } 
    return currentFn;
}

//An example library
UnderstandingThis.ui.Component1 = {
    performTask1: function(options) {
        var settings = {
                opt1: true,
                opt2: false
            },
            _this = this;

        $.extend(settings, options);

        _this._PrivateTask1(settings);
    },
    _PrivateTask1: function(settings) {
        //Some sweet stuff here!
        alert("Private task1: " + settings.from);
    }
}
UnderstandingThis.ui.Component1.performTask1({from: "direct"});
stStringToFunction("UnderstandingThis.ui.Component1.performTask1")({from: "string-to-function"});

Требуется отсутствие объясненияредактирование: 21.02.2012 9:56 (Монтана)

Итак, проблема в том, что библиотека faux (UnderstandingThis.ui.Component1) содержит функцию, которая использует _this (которая установлена ​​на this) и работает нормально при прямом вызове метода.Под этим я подразумеваю в вызове javascript UnderstandingThis.ui.Component1.performTask1().Но если я вызываю эту же задачу через преобразование строки, stStringToFunction("UnderstandingThis.ui.Component1.performTask1")() _this ссылается на window.Но для меня это не имеет смысла.Я работаю с JavaScript только 1,5 года, и эти маленькие нюансы (исходящие из Java / C #) трудно понять.

Ответы [ 3 ]

4 голосов
/ 21 февраля 2012

Если вы позвоните:

foo.bar()

Тогда внутри bar, this будет foo.

Если вы:

var baz = { bar: foo.bar };
baz.bar();

Тогда внутриbar, this - это baz.

Если бы вы:

var bar = foo.bar;
bar();

Тогда внутри bar, this - это window (потому что этообъект по умолчанию).

Ваша функция извлекает функцию из ее контекста и затем вызывает ее (поэтому this равно window).

3 голосов
/ 21 февраля 2012

Ваше первоначальное утверждение:

При непосредственном вызове метода это относится к содержащему объекту

не совсем верно. Псевдопеременная this привязывается на основе ссылки на объект, используемой для доступа к функции (если есть). Если вы создаете экземпляр функции как значение свойства некоторого объекта, а затем вызываете ее по ссылке через это свойство объекта, тогда да, this привязывается к этому объекту. Однако, если вы копируете функцию как значение в свойство другого объекта, то вызов через этот другой объект будет иметь этот объект как this (это всегда проблема «Кто первый?», Когда обсуждаем эту тему: -).

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

0 голосов
/ 21 февраля 2012

Проблема именно в том, что вы подумали, это при втором вызове относится к окну.Вот возможный обходной путь, но лично я сделал бы вещи по-другому.Скрипка здесь http://jsfiddle.net/LsH7V/

/**
 *  converts a string to a function
 */
function stStringToFunction(string) {
    var fnList = string.split(".");
    var currentFn = window;
    var nextFn;
    while(currentFn !== undefined && (nextFn = fnList.shift())) {
        currentFn = currentFn[nextFn];  
    }
    return currentFn;
}

//An example library
UnderstandingThis = {};
UnderstandingThis.ui = {};
UnderstandingThis.ui.Component1 = {

    performTask1: function(options) {
        var settings = {
                opt1: true,
                opt2: false
            };
        if(typeof _this === 'undefined'){    
            _this = this;
            console.log(this);
        }

        $.extend(settings, options);

        _this._PrivateTask1(settings);
    },
    _PrivateTask1: function(settings) {
        //Some sweet stuff here!
        alert("Private task1: " + settings.from);
    }
}
UnderstandingThis.ui.Component1.performTask1({from: "direct"});
stStringToFunction("UnderstandingThis.ui.Component1.performTask1")({from: "string-to-function"});
...