简体   繁体   English

为什么我的对象的属性无法在JavaScript中更新?

[英]Why doesn't my object's property update in JavaScript?

I have a function, which I have prepared for a constructor call ... 我有一个函数,我已经为构造函数调用准备了...

function Queue() {
  if (!(this instanceof Queue)) return new Queue();
    this.capacity = {};
    this._count = 0;
}

And these method are being set on the the prototype property of Queue ...Everything kosher right? 这些方法是在Queue的prototype属性上设置的。

  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');
      }
   };

My question how do i get this._count to increment when the enqueue/count method fires? 我的问题是当入队/计数方法触发时,如何使this._count增加? I keep getting: 我不断得到:

There are 0 items in the queue

I know I could add it on the .prototype property and place that in the count function and have it reference a local var... 我知道我可以将其添加到.prototype属性并将其放置在count函数中,并使其引用本地变量。

Queue.prototype.count = function() {
    var total = Object.keys(this.capacity), count = 0;
    total.forEach(function(elem) {
      this.count++
    });

Queue.prototype.call = call // <-- weird no? Queue.prototype.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');
}

}; };

But that seems not to be elegant... 但这似乎并不优雅...

Thanks in advance! 提前致谢!

You need to bind this within forEach 您需要将此绑定到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');
      }
   };

Try following modification (bind the function): 尝试进行以下修改(绑定功能):

total.forEach(function(elem) {
   this._count++
}.bind(this));

The problems is that this refers to a different object than in the parent function, because in JS, closures do not preserve this but instead the caller decides the this value. 问题是, this指的是不同的对象比父功能,因为在JS,关闭不保留this ,而是调用者决定了this值。 Alternatively, you can use the second thisArg argument of foreach. 或者,您可以使用foreach的第二个thisArg参数。

The existing answers provide good solutions to the problem itself, I just thought I'd elaborate a bit more on the why. 现有的答案为问题本身提供了很好的解决方案,我只是想在此详细说明原因。

this is a reference assigned by the execution context. this是执行上下文分配的引用。 More plainly it's a reference that's determined by the call site of the function. 更明确地说,它是由函数的调用站点确定的引用。 Since you can pass functions around in JavaScript like any other value this can lead to problems being caused by that reference being a moving target. 由于您可以像其他任何值一样在JavaScript中传递函数,因此这可能导致该引用作为移动目标而引起问题。

The issue with your code is that you're referring to this inside of a forEach . 代码的问题在于,您是在forEach引用this代码。 forEach takes a function as an argument and calls it, since what this is pointing to is determined by where the function is called and not where it's defined the value is something different when it gets called. forEach将函数作为参数并调用它,因为this函数所指向的是由调用函数的位置(而不是定义位置)决定的,因此在调用时,值有所不同。 It ends up falling back to whatever global context or undefined if you're in strict mode. 如果处于严格模式下,它最终会退回到任何全局上下文或未定义的状态。

There are a number of different ways to handle the problem. 有很多不同的方法可以解决该问题。

You could store a reference to the outer this on a variable and use it inside the other function. 您可以将外部this的引用存储在变量上,并在其他函数中使用它。

var self = this;
total.forEach(function(elem) {
  self._count++;
});

You could use .bind . 您可以使用.bind It's a function method which returns a function that uses the passed in object as the reference for this no matter where you call it. 这是一个函数方法,无论您在何处调用它,都将返回一个函数,该函数使用传入的对象作为this的引用。

total.forEach(function(elem) {
  this._count++;
}.bind(this));

Or you could use an arrow function. 或者,您可以使用箭头功能。 Arrow functions don't create their own context so they'll just maintain the value of this from the surrounding one. 箭的功能不会产生自己的上下文,这样他们就会保持的值this从周围之一。

total.forEach(() => {
  this._count++;
});

This is a common problem and these are all valid solutions. 这是一个普遍的问题,这些都是有效的解决方案。 They go from least to most elegant in my opinion. 我认为它们从最少到最优雅。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM