新钛云服已总计为您撷取701篇控制技术蔬果
当你在js标识符中看见有初始化super()时,会不能疑惑那个super()究竟有甚么促进作用?在常量中,您能采用super()初始化其子级的缺省,并采用super.<方式名>来出访其子级的方式。
责任编辑将假设您最少对缺省和常量和派生类的基本概念略有介绍。假如你不介绍那些,则可能将须要从Mozilla的Object-oriented JavaScript for beginners已经开始自学。
super并并非只javascript词汇才有–很多其他C词汇,如java, python都有两个super()URL来提供更多对派生类的提及。与Java和Python相同,JavaScript并并非紧紧围绕类承继数学模型构筑的。恰好相反,它扩充了JavaScript的蓝本承继数学模型,以提供更多与类承继完全一致的犯罪行为。
让他们更进一步介绍它,并查阅许多标识符实例。
具体来说,这儿提及的这段话Mozilla’s web docs for classes:
JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript’s existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.
两个简单的常量和派生类的例子将有助于说明这句话的真正含义:
class Fish {constructor(habitat, length){ this.habitat = habitat this.length = length}renderProperties(element){ element.innerHTML = JSON.stringify(this)}}class Trout extends Fish {constructor(habitat, length, variety){ super(habitat, length) this.variety = variety} renderPropertiesWithSuper(element){ element.className=”green” super.renderProperties(element);}}let grouper = new Fish(“saltwater”,”26in”);console.log(grouper);grouper.renderProperties(document.getElementById(“grouper”));let rainbowTrout = new Trout(“freshwater”,”14in”,”rainbow”);console.log(rainbowTrout);//invoke function from parent prototyperainbowTrout.renderProperties(document.getElementById(“rainbowTrout”));//invoke function from childs prototyperainbowTrout.renderPropertiesWithSuper(document.getElementById(“rainbowTroutParent”));
我的例子有两个类:Fish和 Trout。所有的鱼都有栖息地和长度的信息,所以那些属性属于鱼类。鳟鱼也有两个多样性的属性,所以它基于fish又扩充了属性variety。下面是鱼和鳟鱼的缺省:
class fish {constructor(habitat, length){ this.habitat = habitat this.length = length}}class trout extends fish {constructor(habitat, length, variety){ super(habitat, length) this.variety = variety}}
鱼类的缺省定义栖息地和长度,鳟鱼的缺省定义了种类。我必须在鳟鱼的缺省中初始化super(),否则在尝试设置this.variety时能出现错误。那是因为在鳟鱼类的第一行中,我告诉JavaScript鳟鱼是采用extends关键字的“鱼”。
这意味着鳟鱼的上下文包括fish类中定义的属性和方式,和鳟鱼为其自身定义的任何属性和方式。初始化super()本质上使JavaScript知道鱼是甚么,以便能为鳟鱼创建this上下文,其中包括鱼中的所有内容和他们将为鳟鱼定义的所有内容。fish类不须要super(),因为它的“父级”只是JavaScript对象。Fish已处于蓝本承继链的顶部,因此无需初始化super()。
我在trout的缺省中初始化super(habitat, length),使这三个属性在那个上下文中立即可用。实际上还有另一种方式能从trout的缺省中得到相同的犯罪行为。我必须初始化super()来避免引用错误,但我不必采用fish的缺省所期望的参数正确初始化它。
这是因为我不须要采用super()来给fish创建的字段赋值,我只须要确保那些字段存在于那个上下文上。这是JavaScript与真正的类继承数学模型(例如Java)之间的重要区别,根据我的实现方式,以下标识符可能将是非法的:
class trout extends fish {constructor(habitat, length, variety){ super() this.habitat = habitat this.length = length this.variety = variety}}
这种替代的trout缺省使您更难分辨哪些属性属于fish和哪些属性属于trout,但其结果与前面的实例相同。唯一的区别是,在此情况下,不带参数初始化super()会在当前此this的上下文上创建属性habitat和length,而无需为其分配任何内容。
假如我在第三行之后初始化console.log(this),它将显示{habitat:undefined,length:undefined}。第四行和第五行分配值。
我也能在trout的构造函数之外采用super(),以提及派生类上的方式。在这儿,我定义了renderProperties方式,该方式会将类的所有属性显示在我传递给它的HTML元素中。
super()在这儿很有用,因为我希望我的trout类实现两个类似的方式,该方式能完成相同的工作,并且还要多做许多事情—它在更新HTML之前为该元素执定了两个类名。我能通过在相关类函数内初始化super.renderProperties()来重用fish类中的逻辑。
class fish {renderProperties(element){ element.innerHTML = JSON.stringify(this)}}class trout extends fish {renderPropertiesWithSuper(element){ element.className=”green” super.renderProperties(element);}}
你在定义时方式命名很重要。我把我在trout类中的方式叫做renderPropertiesWithSuper(),因为我仍然希望能选择初始化trout.renderProperties(),因为它是在fish类上定义的。
假如我只是将函数命名为trout类中的renderProperties,那将是完全有效的;但是,我将不再能够从trout的实例中直接出访这两个函数–初始化trout.renderProperties将初始化定义在trout上的函数。
这不一定是两个有用的实现方式–能说,像这样初始化super的函数覆盖其子函数的名称是两个更好的模式–但它确实说明了JavaScript允许你的类是多么灵活。
其实也能完全能不采用前面标识符实例中非常有用的super()或extendsURL来实现那个例子,只是不太方便。这就是Mozilla所说的”语法糖”的意思。事实上,假如我把我之前的标识符插入像Babel这样的移植器中,以确保我的类能与旧版本的JavaScript一起工作,它将生成许多更接近下面的标识符。
这儿的标识符大部分是一样的,但你会注意到,假如没有extends和super(),我必须将fish和trout定义为函数并直接出访它们的蓝本。我还必须在第15、16和17行对蓝本做许多额外的改动,并确保trout能在其缺省中传递正确的this上下文(混合承继)。
假如你有兴趣深入介绍这儿发生的事情,Eric Green有一篇优秀的帖子,里面有很多标识符片段,介绍了如何采用和不采用ES2015构筑类和其承继的关系。
function Fish(habitat, length){this.habitat = habitat;this.length = length;}Fish.prototype.renderProperties = function(element){element.innerHTML = JSON.stringify(this)};function Trout(habitat, length, variety){this.super.call(this, habitat, length);this.variety = variety;}Trout.prototype = Object.create(Fish.prototype);Trout.prototype.constructor = Trout;Trout.prototype.super = Fish;Trout.prototype.renderPropertiesWithSuper = function(element){element.className=”green”;this.renderProperties(element);};let grouper = new Fish(“saltwater”,”26in”);grouper.renderProperties(document.getElementById(“grouper”));var rainbowTrout = new Trout(“freshwater”,”14in”,”rainbow”);//invoke function from parentrainbowTrout.renderProperties(document.getElementById(“rainbowTrout”));//invoke function from childrainbowTrout.renderPropertiesWithSuper(document.getElementById(“rainbowTroutParent”));
JavaScript中的类是共享功能的强大方式。例如,React中的类组件依赖于它们。但是,假如您习惯采用另一种采用类承继数学模型的词汇进行面向对象的编程,那么JavaScript的犯罪行为有时可能将会令人惊讶。所以自学蓝本承继的基础知识能帮助阐明如何采用JavaScript中的类。
*原文链接:https://css-tricks.com/what-is-super-in-javascript/