Search code examples
javascriptsapui5thisprototypeextend

Understanding extend and method overwriting


This is a follow-up question from the previous: Why is the parent prototype method still executable after overriding?.

As we see, the literal object {metadata, aaa, init} was initialized by the extend function as a 2nd import variable, so this object should be the object automatically automatically instantiated and represents the extended sub-class. Then inside the object, it inherited the init method from its parent class and overrode it. first call the parent init method to trigger some necessary things, then setup the data for this extended component.

My question is: the init method in this literal object is its own init method, because this refered to the literal object, right? if it's yes, why I can't see it under this proprieties in my debugger tool. enter image description here

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");
    },

  });
});

Solution

  • Hope this other answer clears some things up:

    __proto__ is the actual object that is used in the lookup chain to resolve methods, etc. prototype is the object that is used to build __proto__ when you create an object with new

    This means when you see methods in the prototype section it doesn't mean that the original parent class is overwritten. Your new "class" sap.ui.demo.walkthrough.Component also has/is a prototype and this (which is an instance of your new "class") has it's own __proto__. This new prototype/proto constains methods form the parent prototype and can also define new methods.

    And from the documentation of sap.ui.base.Object.extend:

    Creates a subclass of class sap.ui.base.Object with name sClassName and enriches it with the information contained in oClassInfo.

    oClassInfo might contain three kinds of information:

    • [...]
    • any-other-name: any other property in the oClassInfo is copied into the prototype object of the newly created class. Callers can thereby add methods or properties to all instances of the class. [...]

    So when you do this.__proto you will see the build plan for the current instance. Do this.__proto__.__proto__ to get the build plan from the parent class. Do this.__proto__.__proto__.__proto__ to get the grand parent class (and so on).

    The protos of the parent class are not affected by your child class. But your child classes include everything from the parent class. When you "override" a method you are are adding a method to your new prototype. The parent method still exists in the UIComponent prototype and can therefore be called by explicitly stating UIComponent.prototype.init.apply.