Можно ли определить, был ли вызван метод экземпляра из метода-прототипа? - PullRequest
2 голосов
/ 03 марта 2011
function Foo(x) {
    this.bar = function() { return x; /* but not always */ }
}

Foo.prototype.baz = function() {
    return this.bar(); // Case 2 - should return x
};

var f = new Foo(3);
f.bar(); // Case 1 - should return undefined 
f.baz(); // should return x which is 3 in this case

Итак, bar является методом экземпляра f, который является экземпляром Foo.
С другой стороны, baz является методом-прототипом Foo.

То, что я хотел бы, это:

bar должен возвращать x (аргумент, переданный в функцию конструктора), но только если он вызывается из метода прототипа (метод Foo.prototype).Таким образом, bar должен проверить, является ли текущий контекст выполнения функцией Foo.prototype, и только тогда bar должен вернуть x.

В случае 1 текущий контекст выполнения является глобальным кодом, поэтомувозвращаемое значение вызова bar должно быть undefined.(Под этим я подразумеваю: я хочу, чтобы в этом случае он возвращал undefined.)

Однако в этом случае 2 текущим контекстом выполнения является код функции функции Foo.prototype, поэтому возвращаемое значениеbar звонок должен быть x.

Можно ли это сделать?


Обновление: Реальный пример:

function Foo(x) {
    this.getX = function() { return x; /* but not always */ }
}

Foo.prototype.sqr = function() {
    var x = this.getX(); // should return 3 (Case 2)
    return x * x;
};

var f = new Foo(3);
f.getX(); // should return undefined (Case 1)
f.sqr(); // should return 9

Случай 1: getX isВызов "напрямую" -> возврат не определен
Случай 2: getX вызывается из метода-прототипа -> возврат х

Ответы [ 2 ]

0 голосов
/ 04 марта 2011

Так что это мое собственное решение:

function Foo(x) {
    function getX() { 
        return getX.caller === Foo.prototype.sqr ? x : void 0;
    }
    this.getX = getX;
}

Foo.prototype.sqr = function() {
    var x = this.getX();
    return x * x;
};

var f = new Foo(3);
console.log( f.getX() ); // logs undefined 
console.log( f.sqr() ); // logs 9

Как видите, я должен был определить getX как локальную функцию конструктора Foo (а затем назначить эту функцию экземпляру через this.getX = getX;. Внутри getX я явно проверяю, является ли getX.caller is Foo.prototype.sqr.

0 голосов
/ 03 марта 2011

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

вы используете замыкание, поэтому метод getX имеет доступ к переменной x. Это JavaScript, ведущий себя так, как задумано.

...