当一个函数表现得像一个类但不使用class关键字或"new"关键字时,这被称为什么(在JavaScript中)?

3

我查看了建议的链接,但似乎找不到一个像类一样作用的函数术语(是构造函数吗?它也没有这个关键字!),但不使用new关键字或者class

我在我的代码中使用了这个例子的模式和类模式,但意识到我不知道如何描述前者。

我想部分原因是因为我最近学习了JS,看到了很多class,但是在翻看我的笔记(非 ES5,6,7,2018,2020)时,似乎找不到var aCounter = counterFunction()被称为什么。

我知道我正在做的结果,如何工作等等,但为什么没有constructor(),没有new,没有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个回答

3
那只是返回一个对象字面量的函数,它不像一个类(没有原型,并且正如你指出的,不使用new等)。
存储在aCounter中的属性设置为函数似乎像类方法一样运行,因为它们保持对变量val的引用,但这并不是因为val与实际对象有任何关联。
相反,这些函数是闭包,只要它们自己还活着,就会保持对变量的引用。
所以回答你的问题,你描述的东西没有特定的名称。它只是返回一个对象的函数。
编辑:
你问为什么这种模式中没有constructor()或相关语法。JavaScript中的对象字面量只是名称和值的映射。
const x = { a: 3, b: "hello" };

你不需要为此编写构造函数,也没有原型,因为它没有使用构造函数实例化。另一方面,类和构造函数是稍后将创建的对象的模板,并且这些对象具有原型和构造函数,因为模板包含初始化对象的逻辑。
class A
{
    constructor() 
    {
        this.a = new Date();
        this.b = this.a.toString(); // you cannot do this in an object literal
    }
}

const x = new A();

1
你展示的内容并不是很特别,只是一个具有闭包的普通函数而已。
尽管如此,你可以把它称作一种设计模式
它看起来与揭示模块模式相似,你可以将公共属性和私有属性分开。
以下是一个示例(虽然不太好):

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() 函数来进行操作的。正如你所看到的,没有 classprototypeconstructor

1

问题:

如果一个函数的行为类似于类,但不使用class关键字或“new”关键字(在Javascript中),那么它被称为什么?

答案:

它被称为“工厂函数”。

工厂函数通常返回一个一致类型的对象,但不是工厂函数本身的实例。返回的对象很少继承自工厂函数的prototype属性,调用工厂函数时不需要在函数之前加上new


1

我能理解你可能会被绊倒,让我们一起查看你的代码并探究其中的问题:

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 的状态。由于该变量正在使用中,浏览器的清理过程跳过它,因此函数仍然保留在内存中,我认为直到对象被销毁且函数的变量不再使用为止。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接