Как это называется, когда функция ведет себя как класс, но не использует ни ключевое слово class, ни ключевое слово «new» (в Javascript)? - PullRequest
0 голосов
/ 15 января 2019

Я просмотрел предложенные ссылки, но не могу найти термин для функции, которая действует как класс (это функция конструктора? У этого ключевого слова тоже нет!), Но нет не используйте ключевое слово new и class.

Я использовал шаблон этого примера и шаблон класса в своем коде, но понял, что не знаю, как описать первый.

Я думаю, что это отчасти потому, что я недавно изучил JS, видел, как class много разбрасывался, но просматривал мои заметки не -ES5,6,7,2018,2020 и т. Д. не могу найти то, что var aCounter = counterFunction() призвано для меня жизни.

Я знаю, что является результатом того, что я делаю, как это работает и т. Д., Но почему нет constructor(), нет class, нет etc.prototype.etc шаблона? Я знаю, что создаю объект, вызываю метод, существующий в объекте, и т. Д. Я считаю, что я начинаю бродить.

Ло, пример

const counterFunction = () => {
    let val = 0

    return { 
      increment() { val++ }, 
      getVal() { return val }
    }
}

который является || может быть создан (?) следующим образом:

let aCounter = counterFunction() // where i'm getting tripped up

и работает как

aCounter.increment() // 1
aCounter.increment() // 2
aCounter.getVal() // 2 

Я знаю, что это бессвязно, но помогите! Я думаю, что это заставит вещи щелкать больше внутри, как только эта лексическая часть загадки будет помещена в положение!

Ответы [ 4 ]

0 голосов
/ 15 января 2019

Вопрос:

Как это называется, когда функция ведет себя как класс, но не использует ни ключевое слово class, ни ключевое слово «new» (в Javascript)?

Ответ:

Это называется "фабричной функцией".

Фабричные функции обычно возвращают объект согласованного типа, но не являются экземплярами самой фабричной функции. Возвращаемые объекты редко наследуются от свойства prototype фабричной функции, и для вызова фабричной функции не требуется new до вызова функции.

0 голосов
/ 15 января 2019

То, что вы показали, ничего особенного. Это просто нормальная функция с закрытием.

Хотя вы можете назвать это типом шаблона проектирования .

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

Ниже приведен пример (не очень хороший):

var counter = function(){

  var privateCount = 0;
  var privateHistory = [];
  
  return {
    getVal: function(){
      return privateCount;
    },
    increment: function(){
      privateCount++;
      privateHistory.push('+');
      return this.getVal();
    },
    decrement: function(){
      privateCount--;
      privateHistory.push('-');
      return this.getVal();
    },
    publicHistory: function(){
      return privateHistory;
    }
  }
}

var aCounter = counter();
console.log(aCounter.increment());
console.log(aCounter.decrement());
console.log(aCounter.publicHistory());

Здесь вы не можете напрямую манипулировать закрытыми переменными, которые я вам не раскрываю.

Вы можете манипулировать этими закрытыми переменными только в том случае, если я предоставлю вам эту функцию. В этом случае функции .increment() и .decrement().

Как видите, нет class, нет prototype, нет constructor.

0 голосов
/ 15 января 2019

Я вижу, как вас могут споткнуться, давайте разберем ваш код и выясним, что происходит:

const counterFunction = () => {
    let val = 0

    return { 
      increment() { val++ }, 
      getVal() { return val }
    }
}

На данный момент counterFunction - это переменная, которая указывает на функцию, по сути, это имя функции. ()=>{...} - это тело функции или определение функции, и внутри него оператор return показывает, что он возвращает безымянный объект с двумя методами свойств.


let aCounter = counterFunction() // where i'm getting tripped up

Это вызов ранее определенной вами функции, которая снова возвращает объект двумя методами и присваивает его переменной aCounter. Если вы проделаете то же самое снова для переменной с именем bCounter, они будут содержать два независимых объекта.


and works like

aCounter.increment() // 1
aCounter.increment() // 2
aCounter.getVal() // 2 

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

0 голосов
/ 15 января 2019

Это просто функция, которая возвращает литерал объекта, который не действует как класс (не имеет прототипа и, как вы указали, не использует new и т. Д.).

Функции, которые установлены как свойства этого объекта (который вы храните в aCounter), похоже, действуют как методы класса, потому что они поддерживают ссылку на переменную val живой, но это не потому, что val каким-либо образом связан с реальным объектом.

Вместо этого эти функции являются замыканиями , которые поддерживают ссылку на переменную до тех пор, пока действуют сами функции.

Итак, чтобы ответить на ваш вопрос, у того, что вы описали, нет конкретного имени. Это просто функция, которая возвращает объект.

Edit:

Вы спросили, почему в этом шаблоне отсутствует constructor() или связанный с ним синтаксис. Объектные литералы в JavaScript - это просто сопоставления имен и значений:

const x = { a: 3, b: "hello" };

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

class A
{
    constructor() 
    {
        this.a = new Date();
        this.b = this.a.toString(); // you cannot do this in an object literal
    }
}

const x = new A();
...