【问题标题】:Modulepattern and instances of objects - unexpected changing of propertyvalues模块模式和对象实例 - 属性值的意外更改
【发布时间】:2017-07-08 23:23:30
【问题描述】:

尊敬的社区和 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 圣经中关于闭包和原型的章节之后,我不知道在哪里可以搜索或找到帮助,而不是问你。

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

亲切的问候

吉姆

【问题讨论】:

    标签: javascript object module prototypejs


    【解决方案1】:

    你的代码有一些问题:

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

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

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

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

    严格保护类对象的私有属性/方法并不是真正必要的。建议给它们一些前缀(_ 很常见),并且每当您在代码中点击此前缀时,请仅私下使用该 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)");

    下面是一个拥有一些真正私有成员的类的示例:

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

    【讨论】:

    • 亲爱的 Bulent Vural,非常感谢您的回答。您关于箭头功能的提示是一个很大的帮助和一个新的有价值的见解(=您提出的解决方案无疑是一种改进,但是一个功能(以前适用于一个对象)丢失了。现在 x 和 y 不再是不可见的外部。例如,可以使用 p1.x 直接访问它们(我很抱歉没有在代码片段中明确说明)。因此,我在第一次尝试时尝试了“let x”,因此它们隐藏在范围内。
    • 我用更多信息更新了我的答案。有办法让真正的私人成员,但它真的不值得。反正我举个例子。
    • 非常感谢!您的回答非常有帮助,是我可以进一步研究的好点(=
    猜你喜欢
    • 2018-12-15
    • 2013-11-08
    • 2015-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多