Polymer this.push not working

2019-03-01 00:16发布

问题:

In Polymer 1.x I am trying to push data from my database to an array, but for whatever reason, it suddenly stopped working.

When running this code

ready: function(){
    var leserbriefRef = firebase.database().ref('leserbriefe');
        leserbriefRef.on('value', function(snap) {
          var n = snap.child('numLeserbriefe').val();
          console.log(n);
          this.lbriefe = [];
          for(var i=0; i<n; i++){
                this.push("lbriefe", snap.child('l'+(n - 1 - i)).val());
            }
        });
  }

I get this error message: firebase.js:283 Uncaught TypeError: this.push is not a function

I don't know why. Earlier this week it still worked.

回答1:

This is a common gotcha among js beginners, basically the usage of the this keyword. The context of the this variable inside the anonymous function is not the one you intended (in this case, the element). To solve this, you can use closures[1], .bind[2], or the newer ES2015 arrow functions[3].

Closure

ready: function() {
  // assign this to self
  var self = this;

  var leserbriefRef = firebase.database().ref('leserbriefe');
  leserbriefRef.on('value', function(snap) {
    var n = snap.child('numLeserbriefe').val();
    console.log(n);
    self.lbriefe = [];
    for(var i = 0; i < n; i++){
      self.push("lbriefe", snap.child('l'+(n - 1 - i)).val());
    }
  });
}

.bind

ready: function() {
  var leserbriefRef = firebase.database().ref('leserbriefe');
  leserbriefRef.on('value', function(snap) {
    var n = snap.child('numLeserbriefe').val();
    console.log(n);
    this.lbriefe = [];
    for(var i = 0; i < n; i++){
      this.push("lbriefe", snap.child('l'+(n - 1 - i)).val());
    }
  }.bind(this)); // bind this keyword to element's
}

ES2015 arrow function (might as well go full ES2015)

ready() {
  const leserbriefRef = firebase.database().ref('leserbriefe');
  leserbriefRef.on('value', (snap) => { // arrow functions!
    const n = snap.child('numLeserbriefe').val();
    console.log(n);
    this.lbriefe = [];
    for(let i = 0; i < n; i++){
      this.push("lbriefe", snap.child(`l${n - 1 - i}`).val());
    }
  });
}

Sources:

[1] https://developer.mozilla.org/en/docs/Web/JavaScript/Closures

[2] https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind

[3] https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions



回答2:

well you have to watch for this binding, since the scope of this is changes inside functions.

ready: function(){
    var leserbriefRef = firebase.database().ref('leserbriefe');
        leserbriefRef.on('value', function(snap) {
          var n = snap.child('numLeserbriefe').val();
          console.log(n);
          this.lbriefe = [];
          for(var i=0; i<n; i++){
                this.push("lbriefe", snap.child('l'+(n - 1 - i)).val());
            }
        }.bind(this));
  }