2017-02-19 44 views
0

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

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

亲切的问候

吉姆

回答

0

上有你的代码的一些问题:

  • 你现在的样子用箭头功能。在箭头函数中没有自己的'this'对象。所以用它们来定义原型会得到奇怪的结果。

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

  • 在你的情况下,似乎没有问题使用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)");

+0

亲爱比伦特·武拉尔,非常感谢你为你的回答。关于箭头函数的提示是一个很好的帮助和一个新的有价值的见解(=你提出的解决方案毫无疑问是一种改进,但是其中一个特性(以前曾为一个对象工作过)丢失了。现在x和y不再隐藏例如,可以直接用p1.x访问它们(我很抱歉,因为没有在代码中做这个明确的说明)因此,我尝试了第一次尝试'let x',以便它们隐藏在范围中。 – Jim

+0

我用一些更多的信息更新了我的答案,有很多方法可以让真正的私人成员,但它真的不值得,我反正举了一个例子。 –

+0

非常感谢你!你的回答非常有帮助,是一个很好的观点我可以继续工作(= – Jim

相关问题