javascript - cannot read property push of 'undefined' -


app.controller('ctrl', function($scope){     var socket = io.connect();      this.messages = [];      this.sendmessage = function(){         socket.emit('new message', this.input_message);         this.input_message = '';     }      socket.on('new message', function(data){         this.messages.push(data);     }); }); 

i getting data emitted socket, when try push data messages array, shows error cannot read property push of undefined. wrong doing?

this not work because calling this in socket scope (this.messages.push(data)), not same controller scope. why this.messages undefined, because declared in controller function scope, not in socket callback function scope. in javascript, each function has it's own scope (except arrow functions).

suggestion

app.controller('ctrl', function($scope){    var ctrlcontext = this;    var socket = io.connect();     //using keyword here means    //it's in controller function scope.    this.messages = [];     this.sendmessage = function(){       socket.emit('new message', this.input_message);       this.input_message = '';    }     socket.on('new message', function(data){       //inside callback function have different       //scope, means this.messages undefined.       //but referencing controller function scope,       //are able use messages property set       //outer (controller function) scope.       ctrlcontext.messages.push(data);        //as stated, have call $scope.$apply       //or else digest cycle not triggered.    }); }); 

however, if use this keyword inside socket callback function using function.prototype.bind method, allows set context of executing function.

example

var person = {    name: 'john doe'; }  //create function , bind context person     var changename = function() {    this.name = 'peter smith'; }.bind(person);  console.log(person); // {name: 'john doe'}  changename(person);  console.log(person); // {name: 'peter smith'} 

for solution like:

app.controller('ctrl', function($scope){    var socket = io.connect();     this.messages = [];     var callback = function(data){       this.messages.push(data);    }.bind(this);     socket.on('new message', callback); }); 

Comments