Почему методы класса не могут вызывать другие методы класса или самих себя? - PullRequest
4 голосов
/ 04 июля 2019

Мне любопытно, почему методы не могут вызывать другие методы или сами по себе в javascript.Например, это приводит к ошибке Reference, говорящей, что add не определен.

class sum {
  add(x, amt) {
    if(amt == 0) return x
    return add(x+1, amt-1)
  }
}
summer = new sum()
console.log(summer.add(5,5))

Вы должны использовать this.add () вместо этого.

Теперь я понимаю, что методы преобразуются в функции в прототипе, но я не понимаю, как это объясняет это ограничение, на которое я указываю?

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

Почему это так?

Ответы [ 3 ]

3 голосов
/ 04 июля 2019

Я был в середине иллюстрации этого недостатка, когда @ briosheje сделал комментарий:

function add() {
   console.log('called the wrong add!');
}

class sum {
  add(x, amt) {
    if(amt == 0) return x
    return add(x+1, amt-1)
  }
}
summer = new sum()
console.log(summer.add(5,5))
2 голосов
/ 04 июля 2019

Я постараюсь сделать это "немного" более теоретическим, не вдаваясь слишком глубоко в документацию и т. Д.

Основной ответ на ваш вопрос можно найти, перенеся ваш код в обычный javascript. Для этого вы можете использовать babel онлайн или машинописную онлайн-площадку. В любом случае переданный код будет выглядеть так:

"use strict";
var sum = /** @class */ (function () {
    function sum() {
    }
    sum.prototype.add = function (x, amt) {
        if (amt == 0)
            return x;
        return add(x + 1, amt - 1);
    };
    return sum;
}());
var summer = new sum();
console.log(summer.add(5, 5));

Как видите, метод add принадлежит прототипу sum , который является функцией . Следовательно, вы можете догадаться, что доступ к add в области действия add просто не может неявно привести к вызову функции sum.prototype.add.

Иными словами, если вы посмотрите на правильный код:

class sum {
  add(x, amt) {
    if(amt == 0) return x
    return this.add(x+1, amt-1)
  }
}
var summer = new sum()
console.log(summer.add(5,5))

Вы увидите, что переданный код будет вызывать метод this:

"use strict";
var sum = /** @class */ (function () {
    function sum() {
    }
    sum.prototype.add = function (x, amt) {
        if (amt == 0)
            return x;
        return this.add(x + 1, amt - 1);
    };
    return sum;
}());
var summer = new sum();
console.log(summer.add(5, 5));

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

Небольшое любопытство: если бы вы на самом деле могли получить доступ к this.add, используя add, вы бы не смогли использовать undefined, так как это глобальная переменная , следовательно, вы бы не стали возможность получить к нему доступ и использовать его, потому что он неявно будет this.undefined.

Итак, еще раз, это не о неоднозначности, это о том, как работает javascript functions .

0 голосов
/ 04 июля 2019

Принципиально ООП в Javascript сильно отличается от и других языков.Там на самом деле нет сильного понятия "классы".Классические концепции ООП, такие как классы и экземпляры в Javascript, на самом деле происходят не из «классов», а из правил, связанных с поиском свойств и ключевыми словами this и new.Все остальное - это просто функции, объекты и свойства, некоторые из которых являются «специальными», например prototype.

Например, вы можете собрать «класс» следующим образом:

function Foo() {
    this.bar = 42;
}

function baz() {
    return this.bar;
}

Foo.prototype.baz = baz;

let foo = new Foo;
console.log(foo.baz());

Здесь нет настоящей сплоченности, baz по сути не принадлежит ни к какому классу, но собранные таким образом, они действуют как один.А синтаксис class является лишь тонким слоем над этим механизмом.Итак, если вы напишите add внутри функции , она будет следовать правилам области видимости переменной и будет искать переменную в некоторой окружающей области, в прототипе не будет найдено метода.

...