我有一个函数,我为构造函数调用 ...
准备了这个函数function Queue() {
if (!(this instanceof Queue)) return new Queue();
this.capacity = {};
this._count = 0;
}
这些方法正在Queue
的原型属性上设置......一切都是正确的吗?
Queue.prototype.enqueue = function(name, options) {
this.capacity[name] = options || {};
this.count();
if (this._count > 5) {
return 'Max capacity has been reached—which is five, please dequeue....'
}
};
Queue.prototype.count = function() {
var total = Object.keys(this.capacity);
total.forEach(function(elem) {
this._count++
});
if (this._count == 1) {
console.log(this.capacity[Object.keys(this.capacity)])
console.log( 'There is one item in the queue');
} else {
console.log(this.capacity[Object.keys(this.capacity)])
console.log( 'There are ' + this._count + ' items in the queue');
}
};
我的问题如何在enqueue / count方法触发时让this._count
递增?我一直在说:
There are 0 items in the queue
我知道我可以将它添加到.prototype
属性上并将其放在count函数中并让它引用一个局部变量...
Queue.prototype.count = function() {
var total = Object.keys(this.capacity), count = 0;
total.forEach(function(elem) {
this.count++
});
Queue.prototype.call = call //< - 奇怪的没有?
if (this.count == 1) {
console.log(this.capacity[Object.keys(this.capacity)])
console.log( 'There is one item in the queue');
} else {
console.log(this.capacity[Object.keys(this.capacity)])
console.log( 'There are ' + this.count + ' items in the queue');
}
};
但这似乎并不优雅......
提前致谢!
答案 0 :(得分:2)
您需要在forEach
中绑定它Queue.prototype.count = function() {
var total = Object.keys(this.capacity);
total.forEach(function(elem) {
this._count++
}.bind(this)); //bind the context
if (this._count == 1) {
console.log(this.capacity[Object.keys(this.capacity)])
console.log( 'There is one item in the queue');
} else {
console.log(this.capacity[Object.keys(this.capacity)])
console.log( 'There are ' + this._count + ' items in the queue');
}
};
答案 1 :(得分:1)
尝试以下修改(绑定函数):
total.forEach(function(elem) {
this._count++
}.bind(this));
问题是this
引用了与父函数不同的对象,因为在JS中,闭包不保留this
,而是调用者决定this
值。或者,您可以使用foreach的第二个thisArg
参数。
答案 2 :(得分:1)
现有的答案为问题本身提供了很好的解决方案,我只是想我会详细说明原因。
this
是执行上下文分配的引用。更明显地,它是由函数的调用站点确定的引用。由于您可以像在任何其他值中一样在JavaScript中传递函数,因此可能会导致该引用成为移动目标而导致的问题。
您的代码存在的问题是您在this
内引用了forEach
。 forEach
将一个函数作为一个参数并调用它,因为this
所指向的是由调用函数的位置决定的,而不是它定义的位置,当它得到的值是不同的调用。如果您处于严格模式,它最终会回落到任何全球环境或未定义。
有许多不同的方法可以解决这个问题。
您可以在变量上存储对外this
的引用,并在其他函数中使用它。
var self = this;
total.forEach(function(elem) {
self._count++;
});
您可以使用.bind
。它是一个函数方法,它返回一个函数,该函数使用传入的对象作为this
的引用,无论你在何处调用它。
total.forEach(function(elem) {
this._count++;
}.bind(this));
或者您可以使用箭头功能。箭头函数不会创建自己的上下文,因此它们只会保持周围的this
值。
total.forEach(() => {
this._count++;
});
这是一个常见问题,这些都是有效的解决方案。在我看来,它们从最不优雅到最优雅。