【问题标题】:Variable scope incorrectly set-up in Node.JSNode.JS 中的变量范围设置不正确
【发布时间】:2015-05-30 12:53:09
【问题描述】:

以下是我在 NodeJS 中尝试 BattleShip 的 MCVE。 Grid.set 调用 Grid.place 调用 Grid.place.methodPlace 尝试调用 Grid.cells 并失败。这不是访问此类变量的方法,因为this.cells 不在范围内。访问此变量的正确方法是什么?

我可能把它弄得一团糟。初学者这样做。

"use strict";
function Grid(x, y) {
  var r, c, row;
  this.cells = [];
  this.default = " ";
  for(r = 0 ; r < x ; r++) {
    row = [];
    for(c = 0 ; c < y ; c++) {
      row.push(" ");
    }
    this.cells.push(row);
  }
}

Grid.prototype.place = function(length) {
  function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min)) + min;
  };

  var coordinateList = [];
  function methodPlace(indexOfMethodToUse) {
    if (indexOfMethodToUse == 0) {
      var rndX = getRandomInt(0,(9-length));
      var rndY = getRandomInt(0,9)
      for(var i = 0 ; i <= rndX + length ; i++) {
        if (this.cells[rndX+i][rndY] == this.default) {   // <=====
          coordinateList.push(rndX+i,rndY);
        }
      };
    }
    console.log(coordinateList);
    return coordinateList;
  }
  methodPlace(0);
};

Grid.prototype.set = function(ac) {
  for(var i = 0 ; i <= ac ; i++) {
    this.place(2);
  }
}

var friendlyGrid = new Grid(10,10);
friendlyGrid.set(1,2,1,1);

【问题讨论】:

  • 你可以将methodPlace设为普通方法,这样它就可以像place()set()一样访问this。如果它是故意私有的,你需要这种方式,你必须做self = this 或其他东西让this 在你的私有方法中访问。或者你可以手动调用methodPlacemethodPlace.call(this, 0)
  • @Rudie 到目前为止,它是私有的,我认为这可以保持结构清洁。这是使用函数的方法,所以没有理由把它放在更高的层上,对吧?
  • 没有理由,但可能更干净、更易读、更易调试、更简单的语法等。不需要.call() 和/或self,因为它是一种正常的方法。如果出于充分的理由它不是私有的,我只会将其公开。 .call() 解决方案虽然可读性很强,但也很简短。

标签: node.js scope


【解决方案1】:

至少 2 个解决方案:

  1. 公开方法,如set()place() 如果你这样做,它可以用this.methodPlace(0) 调用,它会知道this
  2. 使用.call() 注入上下文 如果你这样做,它可以用methodPlace.call(this, 0) 调用,它会知道this

如果没有充分的理由将方法设为私有,我会将其公开:更具可读性、更简洁、更好的可调试性、更简单的语法等。如果有充分的理由将其设为私有(访问),我会使用.call()

还有另一种解决方案:

  1. this 复制到self 并在内部使用 我不喜欢这样,因为会有selfthis 浮动,但您可以将类/对象this 复制到self 并使用self 而不是this 在私人方法(this 已更改):
    (这是panta82的解决方案,但使用self而不是that,这说明我不喜欢)

.

var coordinateList = [];
var self = this;
function methodPlace(indexOfMethodToUse) {
  // ... //
      if (self.cells[rndX+i][rndY] == self.default) {   // <=====

【讨论】:

    【解决方案2】:
    Grid.prototype.place = function(length) {
      var that = this;
      // ... the rest of the code
    

    然后,用“that”代替“this”。

    【讨论】:

      猜你喜欢
      • 2018-12-21
      • 1970-01-01
      • 1970-01-01
      • 2016-04-30
      • 1970-01-01
      • 1970-01-01
      • 2019-04-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多