Modulepattern 和对象实例 - 属性值的意外更改

Modulepattern and instances of objects - unexpected changing of propertyvalues

亲爱的社区和 Javascript 向导,

我遇到了一个我无法理解的行为。

我的意图是创建一个模块,它模拟私有变量并控制对象的创建。

我希望下面的例子能说明我想要什么以及我的问题是什么。

const ex = (() => {

  // Creating the constructor for points
  function Point() {
    let x;
    let y;
    
    // I think using prototype is a good idea, because it can be expected that a lot of points are created. So I do not waste memory with a lot of function duplications. 
    Point.prototype.setX = xValue => {
    x = xValue;
    }
    
    Point.prototype.setY = yValue => {
    y = yValue;
    }
    
    Point.prototype.getY = () => {
    return y;
    }
  }
  
  // Returning an interface to create points 
  // but hide their properties.
  return {createPoint: (x,y) => {
    let point = new Point();
    point.setX(x);
    point.setY(y);
    return point;
  }}
})();



p1 = ex.createPoint(1,2);
console.log(p1.getY()); // Result is '2' as expected

p2 = ex.createPoint(3,4);
console.log(p2.getY()); // Result is '4' as expected

console.log(p1.getY()); // Result is '4'..Wait...'4' what? Why?!

我认为明显的来源是我对范围的理解…… 我的假设 were/are 如果我创建一个函数作为原型-属性: 1.该函数是对创建的种类的所有对象可见的。 2. 原型函数作用于使用它的对象的作用域。

根据我的结果,我怀疑数字 2 是否正确。

所以我又试了一次,将属性和方法直接分配给新创建的对象(我希望我这样做了......)

const ex = (() => {

  // Creating the constructor for points
  function Point() {
    this.x;
    this.y;
    
    // I think using prototype is a good idea, because it can be expected that a lot of points are created. So I do not waste memory with a lot of function duplications. 
    this.setX = xValue => {
    x = xValue;
    }
    
    this.setY = yValue => {
    y = yValue;
    }
    
    this.getY = () => {
    return y;
    }
  }
  
  // Returning an interface to create points 
  // but hide their properties.
  return {createPoint: (x,y) => {
    let point = new Point();
    point.setX(x);
    point.setY(y);
    return point;
  }}
})();



p1 = ex.createPoint(1,2);
console.log(p1.getY()); // Result is '2' as expected

p2 = ex.createPoint(3,4);
console.log(p2.getY()); // Result is '4' as expected

console.log(p1.getY()); // Result is '4'..Wait...'4' what? Why?!

但结果没有改变,我无法理解这种行为。 在重新阅读我的 js 圣经中关于闭包和原型的章节后,我不知道在哪里可以搜索或找到帮助而不是问你。

如果你能向我指出我的错误并解释我的代码中出了什么问题,我会很高兴。

亲切的问候

吉姆

您的代码存在一些问题:

  • 你使用箭头函数的方式。箭头函数中没有自己的 'this' 对象。所以用它们来定义原型会得到奇怪的结果

  • 谈这个?啊是的,你需要使用 'this' 在 class 实例中的某处存储一个值。

  • 在您的案例中使用 ES2015 (ES6) 似乎没有问题。为什么不用ES2015's 'Class'定义一个class呢? (它也不给你真正的私人道具,但语法有很大改进)

  • 在另一个函数或闭包中的一个函数中创建一个 class 实例并不会真正隐藏 class 的属性。由于您要返回该对象,因此可以通过它访问这些值。

严格保护 class 对象的 must-be 私有属性/方法并不是真正必要的。建议给它们一些前缀(_ 很常见),每当您在代码中使用此前缀时,请仅私下使用该 var。

const ex = (() => {

  // Creating the constructor for points
  function Point() {
  };

  Point.prototype.setX = function(xValue) {
  console.trace('hmm');
    this.x = xValue;
  };

  Point.prototype.setY = function(yValue)  {
    this.y = yValue;
  };

  Point.prototype.getY = function() {
    return this.y;
  };
  
  return {
    createPoint: (x, y) => {
      let point = new Point();
      point.setX(x);
      point.setY(y);
      return point;
    }
  }
})();



const p1 = ex.createPoint(1, 2);
console.log(p1.getY() + " (Result is '2' as expected)"); 

const p2 = ex.createPoint(3, 4);
console.log(p2.getY() + " (Result is '4' as expected)");
console.log(p1.getY() + " (Result is '2' as expected)");

这里有一个 class 和一些真正的私有成员的例子:

const Point = function(valueX, valueY) {
  let x = valueX;
  let y = valueY;
  this.getY = () => {
    return y;
  };
};

const p1 = new Point(1, 2);
console.log(p1.getY() + " (Result is '2' as expected)"); 

const p2 = new Point(3, 4);
console.log(p2.getY() + " (Result is '4' as expected)");

console.log(p1.getY() + " (Result is '2' as expected)");