0

I am new and learning for JavaScript. I am trying to understand the code line UIComponent.prototype.init.apply(this, arguments) based on JavaScript syntax for below code snippet.

I have read the link for the same question: Prototype & Extend in SAPUI5 (Component.js). The accepted answer there was like this:

What they're doing here is very Java-ish. With extend they're creating a subclass of UIComponent. In this subclass the init method is overridden. When you override a method of the parent object, it's a good practice to call the parents original method from the method that overrides it. By doing so, you're avoiding unexpected situations such as variables that have not been defined at the parent etc. Calling the parent's original method is exactly what the init.apply statement is doing.

Please correct me if it's wrong: here, the parent class refers to is the UIComponent, right? The overridden method init is only done for the extended subclass, but the parent class UIComponent still has its original init without overriding. But UIComponent.prototype.init.apply is calling UIComponent.prototype class, which is even the parent class of UIComponent, right? and most importantly, why do it this way?

I add my debug picture to understand this, and prototype chain, but still not clear.

my debug screenshot

sap.ui.define([
  "sap/ui/core/UIComponent",
  "sap/ui/model/json/JSONModel",
  "sap/ui/model/resource/ResourceModel",
], function (UIComponent, JSONModel, ResourceModel) {
  "use strict";

  return UIComponent.extend("sap.ui.demo.walkthrough.Component", {
    metadata: {
      "interfaces": [
        "sap.ui.core.IAsyncContentCreation",
      ],
      "rootView": {
        "viewName": "sap.ui.demo.walkthrough.view.App",
        "type": "XML",
        /*"async": true, // implicitly set via the sap.ui.core.IAsyncContentCreation interface*/
        "id": "app",
      },
    },

    aaa: function () {
      console.log("aaa");
    },

    init: function () {
      // call the init function of the parent
      UIComponent.prototype.init.apply(this, arguments);
      // set data model
      var oData = {
        recipient: {
          name: "World",
        },
      };
      var oModel = new JSONModel(oData);
      this.setModel(oModel);
      // set i18n model
      var i18nModel = new ResourceModel({
        bundleName: "sap.ui.demo.walkthrough.i18n.i18n",
      });
      this.setModel(i18nModel, "i18n");
    },

  });
});
sisi
  • 7
  • 3
  • Does this help with your first question? https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming) – Marc Apr 17 '22 at 18:36
  • Not really, the general concept from WIKI does not help in fact. Here I just need to talk this particular case :-) – sisi Apr 17 '22 at 21:05
  • _> [...] the parent class `UIComponent` still has its original `init` without overriding._ --> I suggest reading ["Common Misconceptions About Inheritance in JavaScript"](https://link.medium.com/PGJLiKbtjpb) by Eric Elliott. _Classical inheritance_ (e.g. as in Java) and _prototypal inheritance_ (as in JS) aren't same thing. – Boghyon Hoffmann Apr 17 '22 at 23:57
  • I read quickly the link. I think I can understand the difference between Java OO and JS OO in general. And I feel the codes above has similar style as in the link by using the extend keyword. BTW, you may know SAPUI5 library is developed based on jquery also. In above case, I know the parent class UIComponent still has its original init without overriding. but this syntax UIComponent.prototype.init is calling parent class UIComponent's parent class, right? – sisi Apr 18 '22 at 01:18
  • "*the parent class `UIComponent` still has its original `init` without overriding.*" - yes. That original method is `UIComponent.prototype.init`. "*But `UIComponent.prototype.init.apply` is calling `UIComponent.prototype` class, which is even the parent class of `UIComponent`, right?*" - no. `UIComponent.prototype` is not a class. It's just [the object where the shared methods of the `UIComponent` class are stored, to be inherited by all its instances](https://stackoverflow.com/q/572897/1048572). – Bergi Apr 18 '22 at 02:01
  • Gotcha and thanks! Here I wrongly treat keyword `prototype` as `__proto__`, it's a big mistake of me. BTW, the keyword `this` should refer to the object which was instantiated from the extended sub-class 'Component.js'. do you think why it's call this way? – sisi Apr 18 '22 at 03:04
  • Not sure what you mean, what else would `this` refer to? – Bergi Apr 18 '22 at 03:07
  • I mean `this` can refer to the object from subclass `Component` or to its parent class `UIComponent`. But now you are right, here there is only one object which is the one instantiated from the extended sub-class 'Component', so `this` must refer to it. But why not call the init method directly from the sub-class object? I don't understand the explanation: By doing so, you're avoiding unexpected situations such as variables that have not been defined at the parent etc. – sisi Apr 18 '22 at 03:18
  • Look at the method description and the respective source code of `UIComponent#init`: https://github.com/SAP/openui5/blob/14beb0526f853a6ba3cc256712f8b79bbbc6c51f/src/sap.ui.core/src/sap/ui/core/UIComponent.js#L273-L421 --> By calling `UIComponent.prototype.init.apply(this, arguments)` in *your* `init`, you're making sure that those LOC are not missed. That's what jpenninkhof meant in the other question. – Boghyon Hoffmann Apr 18 '22 at 12:20
  • @Hoffmann, thanks for the info. it helped. But still one point not clear. In the overriding init method, it call its UIComponent original init first, then do the normal logic like data model setting up. so the init method is called under the sub-class instance object. but why can't see it directly, but only available at its [[prototype]]. if it's true, it means init the overriding was done at the UIComponent.prototype. But this is not correct, since the overwrite is only for extended object, the parent class prototype still has its initial init method. what's my understanding wrong. – sisi Apr 18 '22 at 20:26

0 Answers0