Javascript: Как получить ссылку на родительский объект, когда «this» было перезаписано «call»? - PullRequest
1 голос
/ 03 января 2011

Хорошо, я ненавижу Javascript прямо сейчас, и я надеюсь, что кто-то может мне помочь.

У меня есть код, который настроен следующим образом:

function Obj1() {
    var me = this;

    this.something = "yay";

    this.getThis = function(){
        return me;
    }
}

Obj1.prototype.method = function() {
    return this.something;
};

function Obj2() {
    this.something = "nay";

}
Obj2.prototype.method = function() {
    return this.something;
}; 



var o1 = new Obj1();
var o2 = new Obj2();

document.write(o1.method()); // Returns yay
document.write(o1.method.call(o2));   // Returns nay, but I need "yay" here

(JSFiddle @http://jsfiddle.net/A9u9K/)

Моя проблема в том, что мне нужно вызвать Obj1.method во втором случае, но я абсолютно не могу получить ссылку на объект :(

Как я могу работатьвокруг этого?

Редактировать: Извините, я неправильно понял мой пример кода :( Обновил его. Я взял большую часть кода из предыдущего ответа, потому что он намного приятнее и все еще иллюстрируетмоя проблема.

Ответы [ 4 ]

4 голосов
/ 03 января 2011

Обновленный ответ :

document.write(o1.method.call(o2)); // Returns nay, but I need "yay" here

Вы сказали, что уже отсортировали его, но как ответ на , который на самом деле не показан здесь на SO, я подумал, что я также могу обновить, чтобы показать это.

Если это method, вы хотите иметь доступ me, даже если он был вызван с другим значением this, вы должны определить его как getThis, как закрытие над me:

function Obj1() {
    var me = this;

    this.something = "yay";

    this.method = function() {
        return me.something;
    };

    this.getThis = function(){
        return me;
    };
}

function Obj2() {
    this.something = "nay";

}
Obj2.prototype.method = function() {
    return this.something;
};

... или, конечно, если вам не нужно, чтобы «что-то» было свойством объекта, просто сделайте его переменным внутри конструктора ( закрытая переменная , например, * 1024). *):

function Obj1() {
    var me = this;
    var something = "yay";

    this.method = function() {
        return something;
    };

    this.getThis = function(){
        return me;
    };
}

function Obj2() {
    this.something = "nay";

}
Obj2.prototype.method = function() {
    return this.something;
};

Оригинальный ответ : (К пересмотру 1 вопроса, в котором не было me.)

но я подумал, что при создании замыкания (как я это делаю в 4) Javascript должен сохранить «this».

this устанавливается полностью в зависимости от того, как вызывается функция, а не от того, где она определена; подробнее об этом здесь и здесь . Но, как вы определили свою getThis функцию, вы можете использовать тот факт, что она закрывается над вызовом конструктора, чтобы решить эту проблему (без каламбура) без использования this:

function Obj1() {
    var me = this;               // <== Use a variable to remember `this`

    this.something = "yay";

    this.method = function() {
        return this.something;
    };

    this.getThis = function(){
        return me;               // <== Return it
    };
}

Живой пример

Подробнее о затворах и трубопроводах, благодаря которым вещь me работает здесь .

Это связано с затратами, и, как правило, с вашим шаблоном определения функций в функции конструктора: каждый отдельный объект, созданный Obj1 и Obj2, получает собственный копия каждой функции. Это может иметь последствия для памяти, если вокруг много таких объектов (но если у вас их много, вам не о чем беспокоиться, и вы получите такие преимущества, как me вещь и другие частные переменные ). В отличие от этого, если вы используете функцию, назначенную прототипу, все экземпляры будут использовать одну общую копию функции.

В вашем примере кода действительно нужно дублировать только функцию getThis для каждого экземпляра (потому что вы полагаетесь на замыкание), так что вы можете сделать это, чтобы избежать ненужного распространения функции:

function Obj1() {
    var me = this;

    this.something = "yay";

    this.getThis = function(){
        return me;
    };
}
Obj1.prototype.method = function() {
    return this.something;
};

function Obj2() {
    this.something = "nay";

}
Obj2.prototype.method = function() {
    return this.something;
};
0 голосов
/ 03 января 2011

Единственный способ решить эту проблему - использовать другой заполнитель для хранения значения this в Obj1 и использования его в функции method() и getThis().

function Obj1() {
    var instance = this;

    this.something = "yay";

    this.method = function() {
        return instance.something;
    }

    this.getThis = function(){
        return instance;
    }
}

Ночто я не могу понять, почему вы это делаете (obj1.getThis.call(obj2).method())?Это явно говорит о том, что вы хотите изменить область действия метода getThis() на что-то другое, тогда вы пытаетесь решить проблему, которая была создана этим использованием.

Можете ли вы сказать, почему вы хотите что-то подобное

0 голосов
/ 03 января 2011

Проблема связана с изменением ссылки для этого объекта с областью действия.Вместо этого, если вы используете this непосредственно в замыкании, используйте локальную переменную, равную этому, т.е. измените ваш Obj1 на L

function Obj1() {
    this.something = "yay";
        var that = this;

    this.method = function() {
        return that.something;
    }

    this.getThis = function(){
        return that;
    }
}
0 голосов
/ 03 января 2011
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...