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);
});
});
我正在获取套接字发出的数据,但是当我尝试将该数据推送到 messages
数组中时,它显示错误无法读取未定义的属性推送
。我做错了什么?
最佳答案
这不起作用,因为您在套接字范围 (this.messages.push(data)
) 中调用 this
,这与 Controller 范围不同。这就是为什么 this.messages
是 undefined
,因为它是在 Controller 函数作用域中声明的,而不是在套接字回调函数作用域中声明的。在 javascript 中,每个函数都有自己的作用域(箭头函数除外)。
建议
app.controller('ctrl', function($scope){
var ctrlContext = this;
var socket = io.connect();
//using the this keyword here means that
//it's in the 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 the callback function we have a different
//scope, which means that this.messages will be undefined.
//but by referencing the controller function scope, you
//are now able to use the messages property set the
//outer (controller function) scope.
ctrlContext.messages.push(data);
//as you stated, you will also have to call $scope.$apply
//or else the digest cycle will not be triggered.
});
});
但是,如果您想在套接字回调函数中使用 this
关键字,您可以使用 function.prototype.bind 来实现。方法,它允许您设置执行函数的上下文。
示例
var person = {
name: 'John Doe';
}
//Create function and bind to 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'}
对于你的解决方案来说,它会是这样的:
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);
});
关于javascript - 无法读取 'undefined' 的属性推送,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39290263/