Javascript OOP/Classes – 多个实例共享相同的数据

前端之家收集整理的这篇文章主要介绍了Javascript OOP/Classes – 多个实例共享相同的数据前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在写一些oop javascript代码.我有几个类的实例,并且每个都有不同的数据.不幸的是,正如您将在下面的示例中看到的那样,它们似乎共享相同的数据.

是否有可能获得我班级的两个独立实例?怎么做呢

的index.html

  1. <html>
  2. <head>
  3. <Meta http-equiv="Content-type" content="text/html; charset=utf-8">
  4. <script type="text/javascript" src="test.js"></script>
  5. <script type="text/javascript">
  6. debugger;
  7.  
  8. // Do this because a page resart seems to keep old data
  9. function SetGlobals()
  10. {
  11. var ui;
  12. var el;
  13.  
  14. // Arr00
  15. ui = document.getElementById("Arr00");
  16. el = arr0.arrayGet(0);
  17. ui.innerHTML = el.m_String;
  18.  
  19. // Arr01
  20. ui = document.getElementById("Arr01");
  21. el = arr0.arrayGet(1);
  22. ui.innerHTML = el.m_String;
  23.  
  24. // Arr10
  25. ui = document.getElementById("Arr10");
  26. el = arr1.arrayGet(0);
  27. ui.innerHTML = el.m_String;
  28.  
  29. // Arr11
  30. ui = document.getElementById("Arr11");
  31. el = arr1.arrayGet(1);
  32. ui.innerHTML = el.m_String;
  33. }
  34.  
  35. function MyOnLoad()
  36. {
  37. SetGlobals();
  38. }
  39. </script>
  40. </head>
  41. <body onload="MyOnLoad()" style="width:100%; height: 100%; padding: 0 0 0 0; margin: 0 0 0 0; overflow: hidden; background:#000000">
  42.  
  43. <div id="divScreen" style="display: block; width:100%; height="100%">
  44. <div id="divMenu" style='float: left; background:#00FF00; border-color: #000000; border-width: 1px;'>
  45. <table>
  46. <tr>
  47. <td>
  48. Array 0/String 0: <label id="Arr00"></label>
  49. </td>
  50. </tr>
  51. <tr>
  52. <td>
  53. Array 0/String 1: <label id="Arr01"></label>
  54. </td>
  55. </tr>
  56. <tr>
  57. <td>
  58. Array 1/String 0: <label id="Arr10"></label>
  59. </td>
  60. </tr>
  61. <tr>
  62. <td>
  63. Array 1/String 1: <label id="Arr11"></label>
  64. </td>
  65. </tr>
  66. </table>
  67. </div>
  68. <div id="divMain" style='height: 100%; background:#0000FF; margin-left: 250px; border-color: #000000; border-width: 1px;'>
  69. </div>
  70. </div>
  71. </body>
  72. </html>

Test.js

  1. var BaseARR = function()
  2. {
  3. _arr = []; // new Array();
  4.  
  5. // Public functions that can access private members
  6. this.Add = function(arg)
  7. {
  8. var i,addAt;
  9.  
  10. if(arg==null || (addAt = FindEnterPos(arg))<0)
  11. return false;
  12.  
  13. // since adding and not deleting anything,nothing of value will be returned
  14. _arr.splice(addAt,arg);
  15.  
  16. return true;
  17. };
  18. // This finds the entry position for in
  19. FindEnterPos = function(arg)
  20. {
  21. return (_arr.length + 1);
  22. };
  23. this.arrayGet = function(i)
  24. {
  25. return ((_arr != null && i >= 0 && i < _arr.length) ? _arr[i] : null);
  26. };
  27. };
  28.  
  29. var stringId = function(id,str)
  30. {
  31. // public has a this.,privates have just var
  32. this.m_Id = id; // int
  33. this.m_String = str; // string
  34. };
  35.  
  36. // This so allow statics
  37. var stringIdARR = function()
  38. {
  39. BaseARR.call(this);
  40. };

解决方法

您的代码中存在各种问题.让我试着解释一下.

首先,强烈建议不要在JavaScript中将开放块括号放在一行上.为什么你会问?运行这两个代码片段:

  1. // using "braces on same line" style
  2. (function () {
  3. return {
  4. key: 'value'
  5. };
  6. })();
  7.  
  8. // using "braces on line by themself"-style
  9. (function ()
  10. {
  11. return
  12. {
  13. key: 'value'
  14. }
  15. })();

两个片段都会返回不同的结果,尽管唯一的区别是大括号的位置.其原因是分号插入.在JavaScript中,分号是可选的.因此,如果解析器找到换行符并且换行符前面的构造有意义,它将插入分号.在第二个例子中,这是在return语句之后发生的事情.如果将大括号放在与前一个语句相同的行上,则可以规避此类错误.

接下来你错了就是JavaScript有类. JavaScript是一种面向对象的语言,但与大多数其他面向对象语言不同,它没有类.在JavaScript中,对象直接从其他对象(它们所谓的原型)继承.你当前所指的是一个类实际上是一个构造函数,当使用new关键字调用时,它将创建一个新对象,它将从构造函数原型字段中存储的任何对象继承.

  1. var anObject = {
  2. key: 'value'
  3. };
  4. function MakeAnObject() {
  5. }
  6.  
  7. MakeAnObject.prototype = anObject;
  8.  
  9. var o = new MakeAnObject();
  10.  
  11. console.log(o.key); // will output 'value'

如果设置属性,则在对象本身上设置proerty,在设置属性时永远不会访问原型链.

如果您从一个没有该属性的对象中读取属性,JavaScript将搜索属性的对象原型链(即所有相互继承的对象),如果找到则返回它.

如果一个oject本身有一个属性,它的原型链就不会被搜索,所以你可以通过在对象self上设置porperty来“覆盖”一个对象继承的属性.

请看以下示例:

  1. function MakeThing() {
  2. }
  3.  
  4. MakeThing.prototype = {
  5. key: 'value'
  6. };
  7.  
  8. var o1 = new MakeThing(),o2 = new MakeThing();
  9.  
  10. console.log(o1); // will output 'value'
  11. console.log(o2); // will output 'value'
  12.  
  13. o2.key = 'other';
  14.  
  15. console.log(o1); // will output 'value'
  16. console.log(o2); // will output 'other'
  17.  
  18. MakeThing.prototype.key = 'changed';
  19.  
  20. console.log(o1); // will output 'changed'
  21. console.log(o2); // will output 'other'
  22.  
  23. delete o2.key;
  24.  
  25. console.log(o1); // will output 'changed'
  26. console.log(o2); // will output 'changed'

考虑到所有这些,我将不得不告诉你:在JavaScript中的对象上没有公共和私有成员这样的东西.会员将永远是公开的.有些模式试图使用闭包来隐藏对象中的某些信息,但它们的功能与传统编程语言中的私有成员非常不同.更糟糕的是:这些模式很笨重,产生了糟糕且非常糟糕的代码.我建议如果你没有绝对要求,不要使用它们.

那么,这意味着什么?首先,如果要在多个对象之间共享属性方法,则必须从同一原型继承,并且该原型必须包含这些属性方法.其次,如果您在此设置某些内容,它将在当前实例上设置,而不是在原型上设置.第三,只有按惯例设立priavte和公共成员.如果您绝对要求某些子系统严格隐藏某些信息,那么就有这样的模式(Crockford封口机开封应该会产生可用的结果).

所有这些都说明了在修复对象时的快速尝试:

  1. function BaseAAR {
  2. this._arr = []; // note >this<. You created a global array in your code.
  3. };
  4.  
  5. BaseAAR.prototype.add = function(arg) {
  6. var i,addAt;
  7.  
  8. // always use identity (triple) operators when comparing to null!
  9. if (arg === null || (addAt = this.findEnterPos(arg))<0)
  10. return false;
  11.  
  12. // since adding and not deleting anything,nothing of value will be returned
  13. this._arr.splice(addAt,arg);
  14. return true;
  15. };
  16. // This finds the entry position for in
  17. BaseAAR.prototype.findEnterPos = function() {
  18. return (this._arr.length + 1);
  19. };
  20. BaseAAR.prototype.arrayGet = function(i) {
  21. return ((this._arr !== null && i >= 0 && i < this._arr.length) ? this._arr[i] : null);
  22. };
  23.  
  24.  
  25. function StringIdAAR(id,str) {
  26. BaseAAR.call(this); // invoke the constructor of the base object
  27. this.m_Id = id; // int
  28. this.m_String = str; // string
  29. }
  30.  
  31. StringIdAAR.prototype = BaseAAR.prototype; // innherit from StringIdAAR prototype

我不完全确定这段代码是否真的仍然按照你的意愿去做,但你应该明白JavaScript中面向对象的模式应该是什么样子.
如果你想阅读更多关于如何编写好的JavaScript的信息,你应该完全得到Douglas Crockford的书“JavaScript:The Good Parts”.

更新:我还写了一个article on JavaScript object orientation and prototype based inheritance.这可能是路过这里的人感兴趣的.

猜你在找的JavaScript相关文章