当一个函数的行为像一个类但不使用 class 关键字或“new”关键字(在 Javascript 中)时,它会调用啥?
Posted
技术标签:
【中文标题】当一个函数的行为像一个类但不使用 class 关键字或“new”关键字(在 Javascript 中)时,它会调用啥?【英文标题】:What is it called when a function behaves like a class but doesn't use the class keyword, nor "new" keyword (in Javascript)?当一个函数的行为像一个类但不使用 class 关键字或“new”关键字(在 Javascript 中)时,它会调用什么? 【发布时间】:2019-06-09 01:53:14 【问题描述】:我查看了suggested 链接,但似乎找不到像类一样的函数的术语(它是构造函数吗?也没有那个关键字!)但没有使用new
关键字,也不是 class
。
我在我的代码中同时使用了这个示例的模式和类模式,但意识到我不知道如何描述前者。
我认为这部分是因为我最近学习了 JS,看到class
被扔了很多,但查看我的笔记 not-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
我知道这是漫无边际的,但帮助!我认为一旦这个词汇拼图被放置到位,它会让事情在里面更加点击!
【问题讨论】:
【参考方案1】:这只是一个返回对象字面量的函数,它不像一个类(没有原型,并且正如您所指出的,不使用 new
等)。
设置为该对象的属性的函数(您存储在aCounter
中)似乎像类方法一样,因为它们保持对变量val
的引用仍然有效,但这不是因为val
以任何方式与实际对象相关联。
相反,这些函数是closures,只要函数本身还活着,它们就会保持对变量的引用。
所以为了回答你的问题,你所描述的并没有特别的名字。它只是一个返回对象的函数。
编辑:
您问为什么此模式中没有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();
【讨论】:
【参考方案2】:问题:
当一个函数表现得像一个类但不使用 class 关键字或“new”关键字(在 Javascript 中)时,它会调用什么?
答案:
它被称为“工厂函数”。
工厂函数通常返回一个类型一致的对象,但不是工厂函数本身的实例。返回的对象很少会继承工厂函数的prototype
属性,并且调用工厂函数不需要在调用函数之前使用new
。
【讨论】:
【参考方案3】:您所展示的并没有什么特别之处。它只是一个带有闭包的普通函数。
不过,您可以将其称为design pattern 的类型。
它看起来类似于Revealing Module Pattern,您可以将公共财产和私人财产分开。
下面是一个例子(不是一个好例子):
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
。
【讨论】:
【参考方案4】:我知道你可能会被绊倒,让我们检查你的代码并探索发生了什么:
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
的状态就可以被保留下来。因为变量在使用中,浏览器的清理过程会跳过它,所以函数还是保存在内存中,相信直到对象被销毁,函数的变量不再使用。
【讨论】:
以上是关于当一个函数的行为像一个类但不使用 class 关键字或“new”关键字(在 Javascript 中)时,它会调用啥?的主要内容,如果未能解决你的问题,请参考以下文章
AngularJS ng-class 添加类但在更改时不删除它
ValueError:`class_weight`必须包含数据中的所有类。类{1,2,3}存在于数据中,但不存在于`class_weight`中