“Uncaught TypeError: this._isDateType is not a fun

2019-07-11 07:55发布

问题:

I've got every time a type error that a function definition could not be found. The code looks as follow:

return BaseController.extend("ch.micarna.weightprotocol.controller.Calendar", {
  onInit: function () {
    console.log(this._isDateType(new Date()));
    let oHbox = this.byId("calendar-container");
    let oTodayDate = new Date();
    let oEndDate = this._getLastDayOfMonth(oTodayDate);
  },

  _getLastDayOfMonth: (oBegin) => {
    if (this._isDateType(oBegin)) {
      throw new TypeError("The given parameter is not type of date.");
    }
    return new Date(oBegin.getFullYear(), oBegin.getMonth() + 1, 0);
  },

  _isDateType: (oDate) => {
    return Object.prototype.toString.call(oDate) === "[object Date]";
  },

});

The problem is the _isDateType function that could not be found when it is called inside the _getLastDayOfMonth function. I set the break point:

and as you can see, the function is undefined and I do not know why.

At the beginning of the onInit function, I called the _isDateType function:

console.log(this._isDateType(new Date()));

and it supply the result as expected.

What am I doing wrong?

回答1:

Replace the arrow function

_getLastDayOfMonth: (oBegin) => {
  // this....
},

with the normal function expression:

_getLastDayOfMonth: function(oBegin) {
  // this...
},

By this, the _getLastDayOfMonth can freely access other methods within the Controller instance.

Why it didn't work with arrow function

  • First of all, it's important to know that arrow functions bind their context lexically.

    An arrow function expression has a shorter syntax than a function expression and does not have its own this. [source]

    For example, it's not possible to call .bind on arrow functions. They get their this from the closure when evaluated.

  • Since this was not an instance of the Controller but rather the window object when BaseController.extend was called, calling this._isDateType inside the arrow function was equivalent to window._isDateType.


回答2:

What you cannot do is refer to a property of an "under construction" object from elsewhere in the object literal syntax. In cases where you want to do that, you do need one or more separate assignment statements.

For example, move your code as follows:

var temp = BaseController.extend("ch.micarna.weightprotocol.controller.Calendar", {

onInit: function () {

  console.log(this._isDateType(new Date()));

  let oHbox = this.byId("calendar-container");

  let oTodayDate = new Date();
  let oEndDate = this._getLastDayOfMonth(oTodayDate);

}

});

temp._isDateType = (oDate) => {
  return Object.prototype.toString.call(oDate) === "[object Date]";
};

temp._getLastDayOfMonth = (oBegin) => {

  if (this._isDateType(oBegin)) {
    throw new TypeError("The given parameter is not type of date.");
  }
  return new Date(oBegin.getFullYear(), oBegin.getMonth() + 1, 0);
}

return temp;

The idea is to split function assignments into several statements;



回答3:

The element this can be used inside a function to get the temporary value of the element. To use the _isDateType method you should create an attribute inside the method and fill it with the 'this' value.

return BaseController.extend("ch.micarna.weightprotocol.controller.Calendar", {
var temp= null;
onInit: function () {
  temp = this;
  console.log(temp._isDateType(new Date()));

  let oHbox = temp.byId("calendar-container");

  let oTodayDate = new Date();
  let oEndDate = temp._getLastDayOfMonth(oTodayDate);

},

_getLastDayOfMonth: (oBegin) => {

  if (temp._isDateType(oBegin)) {
    throw new TypeError("The given parameter is not type of date.");
  }
  return new Date(oBegin.getFullYear(), oBegin.getMonth() + 1, 0);
},

_isDateType: (oDate) => {
  return Object.prototype.toString.call(oDate) === "[object Date]";
}