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

时间:2017-02-19 19:20:51

标签: javascript object module prototypejs

亲爱的社区和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?!

我认为明显的来源是我理解范围的湖泊...... 我的假设是,如果我创建一个函数作为原型属性: 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-bible中的闭包和原型的章节之后,我不知道在哪里可以搜索或找到帮助而不是问你。

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

亲切的问候

吉姆

1 个答案:

答案 0 :(得分:0)

您的代码存在一些问题:

  • 您使用箭头功能的方式。没有自己的'这个'箭头函数中的对象。因此,使用它们来定义原型会得到奇怪的结果。

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

  • 在您的情况下,似乎没有问题可以使用ES2015(ES6)。为什么不使用ES2015's 'Class'来定义一个类? (它也没有给你真正的私人道具,但语法得到了很大改善)

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

严格保护必须是私有属性/类对象的方法并不是必需的。建议给它们一些前缀(_是常见的),每当你在你的代码上点击这个前缀时,只能私下使用它。



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)");




以下是一个拥有一些真实私人成员的课程的例子:



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)");