1.从构造函数返回一个对象(单例)构造函数返回它所属类的实例以外的东西是非常奇怪的。好吧,在JavaScript中,这实际上是可能的。让我们以一个简单的汽车类为例。classCar{make='';model='';doorsCount=4;wheelsCount=4;constructor(make,model){this.make=make;this.model=model;}}默认情况下,newCar(...)将返回一个类的实例对象,我们可以使用它来访问该类的属性和方法。constjeepWrangler=newCar('jeep','wrangler');jeepWrangler.doorsCount=2;吉普牧马人模型;//wrangler我们实际上可以从构造函数返回一些东西,例如,一个不同的对象。classCar{make='';model='';doorsCount=4;wheelsCount=4;constructor(make,model){this.make=make;this.model=model;return{different:true}}}这是只是意味着当我们实例化类时,我们得到返回的对象。constjeepWrangler=newCar('jeep','wrangler');吉普牧马人模型;//undefinedjeepWrangler.different;//true但这只有在你返回一个对象时才会有这个效果。如果您返回一个原语,该类将正常工作。汽车类{make='';model='';doorsCount=4;wheelsCount=4;constructor(make,model){this.make=make;this.model=model;return12}}constjeepWrangler=newCar('吉普车','牧马人');吉普牧马人模型;//wrangler那么你能用这个奇怪的东西做什么呢?好吧,你可以创建单例:无论你实例化多少次,你总是得到相同的实例。Angular根提供的服务是单例模式可以做什么的一个例子。constLocalStore=(()=>{constdata=newMap();letinstance=null;returnclassLocalStore{constructor(){if(instance===null){instance=this;}returninstance;}}})();conststore1=newLocalStore();conststore2=newLocalStore();store1===store2//真正的单例适用于日志记录、分析、数据库、存储的全局类,以及创建全局变量的替代方法。您可以使用这个技巧来控制类返回的内容。2.防止类实例化(抽象类)JavaScript本身不支持抽象类的概念。抽象类是只能扩展不能实例化的类。但是,有一种不包含装饰器的hacky方法可以做到这一点。classCar{make='';model='';doorsCount=4;wheelsCount=4;constructor(make,model){this.make=make;this.model=model;}}classBMWextendsCar{<-扩展Carconstructor(模型){super('bmw',model);this.model=model;}}constbmwM3=newCar('bmw','m3');<-instantiateCar我们可以利用从类内部访问类构造函数名称的优势构造函数事实。classCar{make='';model='';doorsCount=4;wheelsCount=4;constructor(make,model){this.make=make;this.model=model;console.log(this.constructor.name)}}constbmwM3=newCar('bmw','m3');构造函数名称将始终是您用来实例化的类,这意味着我们可以使用它来了解类是扩展还是实例化。classCar{make='';model='';doorsCount=4;wheelsCount=4;constructor(make,model){this.make=make;this.model=model;if(this.constructor.name==='Car'){thrownewError('Carclassisabstract.Itcanonlybeextended')}}}classBMWextendsCar{constructor(model){super('bmw',model);this.model=model;}}constbmwM1=newBMW('m1');//有效!!constbmwM3=newCar('bmw','m3');//如果构造函数名称与你检查的类匹配,则直接实例化该类。否则,它由扩展它的类实例化。就像这样,您可以创建只能扩展的类,这对于创建基类非常有用。3.运行时的多个类扩展(mixins)在OOP中,您可以让一个类扩展另一个类,并且您必须在代码执行之前这样做。对于一些非常具体的问题,我一直在代码中探索的一件事是在运行时扩展类的想法。为了向您解释我的意思,我想让您想象您正在玩游戏并且您有一个Person类来表示您的角色。让我们使用像这样简单的东西。classPerson{name;dob;constructor(name,dob){this.#name=name;this.#dob=newDate(dob)}getname(){returnthis.#name;}getage(){return(newDate().getFullYear()-this.#dob.getFullYear())}}constjohnDoe=newPerson('JohnDoe','09/12/1990');johnDoe.age;//32johnDoe.name;//'JohnDoe假设在整个游戏过程中,这个人被AWS聘为软件工程师。我们可以使用构造函数为此创建一个新函数。functionEmployee(company,startingDate,title){this.occupation={company,startingDate:newDate(startingDate),title,}this.quit=()=>{deletethis.occupation;deletethis.quit;}}为我们的用户提供此功能,我们可以像这样在运行时扩展它:Employee.call(johnDoe,'AWS','02/05/2020','softwareengineer');至此,我们就可以得到职业属性和辞职能力了。johnDoe.occupation;//{company:'AWS',startingDate:WedFeb05202000:00:00GMT-0500(EasternStandardTime),title:'软件工程师'}johnDoe.quit();johnDoe.occupation;//undefinedjohnDoe.quit;//undefined当然,这只是解决此类问题的一种方式,我们也可以尝试插件模式。我想说明的是用多个东西扩展一个类的能力。这也是实现混合的一种方式,从一个基类开始并在运行时或前期扩展它。这实际上是我们在JavaScript中引入类之前扩展类的方式。该类只是构造函数和原型工作的语法糖。以下类可以扩展构造函数。classPersonextendsEmployee{name;dob;constructor(name,dob,company,startingDate,title){super(company,startingDate,title);this.#name=name;this.#dob=newDate(dob)}getname(){returnthis.#name;}getage(){return(newDate().getFullYear()-this.#dob.getFullYear())}}上面是一样的,但是必须在代码运行之前设置,需要Person类接受更多参数。mixin方法允许您将代码拆分为更小的构造函数,以处理包括私有数据在内的所有逻辑。这允许您在代码运行时扩展您的类实例。文章来源:web前端开发
