2

I'm having an issue with the 'this' scope when using ES6.

Here´s a link to my original and transpiled code with BabelJS.

When calling a function to remove an item from an array the scope of 'this' is undefined.

How can I make this to make this without redefining this (let self = this)?

"use strict";

var _createClass = (function() {
  function defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
      var descriptor = props[i];
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      if ("value" in descriptor) descriptor.writable = true;
      Object.defineProperty(target, descriptor.key, descriptor);
    }
  }
  return function(Constructor, protoProps, staticProps) {
    if (protoProps) defineProperties(Constructor.prototype, protoProps);
    if (staticProps) defineProperties(Constructor, staticProps);
    return Constructor;
  };
})();

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
}

var Point = (function() {
  function Point() {
    var _this = this;

    _classCallCheck(this, Point);

    this.myArray = ko.observableArray([1, 2, 3, 4]);
    this.removeFromArrayWithArrowFunction = function(value) {
      _this.myArray.remove(value);
    };
  }

  _createClass(Point, [{
    key: "removeFromArray",
    value: function removeFromArray(value) {
      this.myArray.remove(value);
    }
  }]);

  return Point;
})();

ko.applyBindings(new Point());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span data-bind="text: ko.toJSON(myArray)"></span>
<h2>Issues with this scoping when using a regular Function</h2>
<ul data-bind="foreach: myArray">
  <li>
    <a href="#" data-bind="text: $data, click: $parent.removeFromArray"></a>

  </li>
</ul>

<h2>Works as expected using an arrow function</h2>
<ul data-bind="foreach: myArray">
  <li>
    <a href="#" data-bind="text: $data, click: $parent.removeFromArrayWithArrowFunction"></a>

  </li>
</ul>
Carlos Mendes
  • 1,900
  • 1
  • 18
  • 33
  • 1
    This is not really an ES6 problem, you're binding the `click` event to an object's method. You're losing the context of `this`. You need to bind the method to the parent object. – Jeff Mercado Jul 13 '15 at 13:51
  • Thank you @JeffMercado. Any recommendation on how to achieve it? – Carlos Mendes Jul 13 '15 at 13:59
  • 2
    sroes provided an ES6 solution. Otherwise, use any of the approaches outlined [here](http://stackoverflow.com/questions/10737494/context-of-this-when-triggering-method-on-root-from-child). – Jeff Mercado Jul 13 '15 at 14:21

1 Answers1

2

If you use viewmodel functions directly in your bindings, you're losing the context of this like Jeff Mercado explained. Arrow functions capture the this value of the enclosing context, so if you use the arrow function notation, you don't have to worry about var self = this.

So change the following:

removeFromArray(value) {
  this.myArray.remove(value);
}

Into:

removeFromArray = (value) => {
  this.myArray.remove(value);
}

And it should work fine.

See babel

sroes
  • 14,663
  • 1
  • 53
  • 72
  • 5
    Please add an explanation to your solution, in particular that you are making use of a proposal for ES7. This is not ES6. Also, your solution is basically what the OP did with `this.removeFromArrayWithArrowFunction = value => { this.myArray.remove(value);}`. – Felix Kling Jul 13 '15 at 14:40
  • 1
    You're right @FelixKling. I tried this locally and it didn't work since I'm not using the experimental Babel Features. Any other options? – Carlos Mendes Jul 13 '15 at 15:02
  • 1
    Just what the OP already did, setting the function inside the constructor. – Felix Kling Jul 13 '15 at 16:58
  • @FelixKling do you know what is the name of the feature proposal that enables this sintax in ES7? Thanks in advance – Carlos Mendes Jul 13 '15 at 17:05
  • @CarlosMendes: "Class properties" https://gist.github.com/jeffmo/054df782c05639da2adb – Felix Kling Jul 13 '15 at 18:49