Javascript OOP / Classes - multiple instances use the same data

I am writing some javascript oop code. I have several instances of the class and put different data each time. Unfortunately, as you will see in the following example, they seem to use the same data.

Can I get two separate instances of my class? How it will be done.

Index.html

<html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <script type="text/javascript" src="test.js"></script> <script type="text/javascript"> debugger; // Do this because a page resart seems to keep old data function SetGlobals() { var ui; var el; // Arr00 ui = document.getElementById("Arr00"); el = arr0.arrayGet(0); ui.innerHTML = el.m_String; // Arr01 ui = document.getElementById("Arr01"); el = arr0.arrayGet(1); ui.innerHTML = el.m_String; // Arr10 ui = document.getElementById("Arr10"); el = arr1.arrayGet(0); ui.innerHTML = el.m_String; // Arr11 ui = document.getElementById("Arr11"); el = arr1.arrayGet(1); ui.innerHTML = el.m_String; } function MyOnLoad() { SetGlobals(); } </script> </head> <body onload="MyOnLoad()" style="width:100%; height: 100%; padding: 0 0 0 0; margin: 0 0 0 0; overflow: hidden; background:#000000"> <div id="divScreen" style="display: block; width:100%; height="100%"> <div id="divMenu" style='float: left; background:#00FF00; border-color: #000000; border-width: 1px;'> <table> <tr> <td> Array 0/String 0: <label id="Arr00"></label> </td> </tr> <tr> <td> Array 0/String 1: <label id="Arr01"></label> </td> </tr> <tr> <td> Array 1/String 0: <label id="Arr10"></label> </td> </tr> <tr> <td> Array 1/String 1: <label id="Arr11"></label> </td> </tr> </table> </div> <div id="divMain" style='height: 100%; background:#0000FF; margin-left: 250px; border-color: #000000; border-width: 1px;'> </div> </div> </body> </html> 

Test.js

 var BaseARR = function() { _arr = []; // new Array(); // Public functions that can access private members this.Add = function(arg) { var i, addAt; if(arg==null || (addAt = FindEnterPos(arg))<0) return false; // since adding and not deleting anything, nothing of value will be returned _arr.splice(addAt, 0, arg); return true; }; // This finds the entry position for in FindEnterPos = function(arg) { return (_arr.length + 1); }; this.arrayGet = function(i) { return ((_arr != null && i >= 0 && i < _arr.length) ? _arr[i] : null); }; }; var stringId = function(id, str) { // public has a this. , privates have just var this.m_Id = id; // int this.m_String = str; // string }; // This so allow statics var stringIdARR = function() { BaseARR.call(this); }; 
+6
source share
2 answers

There are various problems in the code. Let me try to explain them.

First, it is highly recommended that you do not place the brackets of the opening block on the same line in JavaScript. Why can you ask? Remove these two code snippets:

 // using "braces on same line" style (function () { return { key: 'value' }; })(); // using "braces on line by themself"-style (function () { return { key: 'value' } })(); 

Both fragments return different results, although the only difference is the positioning of the curly braces. The reason for this is the semicolon. In JavaScript, semicolons are optional. Therefore, if the parser finds a newline character, and the construction infront of the newline makes sense, it will insert a semicolon. In the second example, this happens after the return statement. If you put curly braces on the same line as the previous one, you can get around such errors.

The next thing you are mistaken is that JavaScript has classes. JavaScript is an object-oriented language, but unlike most other object-oriented languages, it does not have classes. JavaScript objects are inherited directly from other objects (their so-called prototypes). What you currently consider a class is actually a design function that, when called using the new keyword, will create a new object that inherits any object stored in the prototype constructor field.

 var anObject = { key: 'value' }; function MakeAnObject() { } MakeAnObject.prototype = anObject; var o = new MakeAnObject(); console.log(o.key); // will output 'value' 

If you set the property, the protector will be installed on the object itself, it will never gain access to the prototype chain when setting the property.

If you read a property of an object that does not have this property, JavaScript will look for a chain of object prototypes (that is, all objects inheriting from each other) for this property and return them if found.

If an object has its own property, the prototype chain will not search, so you can "override" objects, inherited properties by setting the neatness of the objects yourself.

Take a look at the following example:

 function MakeThing() { } MakeThing.prototype = { key: 'value' }; var o1 = new MakeThing(), o2 = new MakeThing(); console.log(o1); // will output 'value' console.log(o2); // will output 'value' o2.key = 'other'; console.log(o1); // will output 'value' console.log(o2); // will output 'other' MakeThing.prototype.key = 'changed'; console.log(o1); // will output 'changed' console.log(o2); // will output 'other' delete o2.key; console.log(o1); // will output 'changed' console.log(o2); // will output 'changed' 

Given all this, I will have to tell you: in JavaScript there is no object of public and private elements. Members will always be public. There are some patterns that try to hide certain information in an object using closures, but they function much more strongly than private members in a traditional programming language. And even worse: these patterns are clumsy, they produce awful and very poorly executed code. I suggest not using them unless you need absolute necessity.

So what does all this mean? First, if you want to share attributes and methods between several objects, they will have to inherit the same prototype, and this prototype must contain these attributes and methods. Secondly, if you install something on this , it will be installed in the current instance, and not on the prototype. Thirdly, there are priavte and public members only by agreement. If you absolutely require that certain information be strictly hidden from a particular subsystem, there are templates for this (Clackford sealer unsealer should give acceptable results).

All that is said here will quickly try to fix your objects:

 function BaseAAR { this._arr = []; // note >this<. You created a global array in your code. }; BaseAAR.prototype.add = function(arg) { var i, addAt; // always use identity (triple) operators when comparing to null! if (arg === null || (addAt = this.findEnterPos(arg))<0) return false; // since adding and not deleting anything, nothing of value will be returned this._arr.splice(addAt, 0, arg); return true; }; // This finds the entry position for in BaseAAR.prototype.findEnterPos = function() { return (this._arr.length + 1); }; BaseAAR.prototype.arrayGet = function(i) { return ((this._arr !== null && i >= 0 && i < this._arr.length) ? this._arr[i] : null); }; function StringIdAAR(id, str) { BaseAAR.call(this); // invoke the constructor of the base object this.m_Id = id; // int this.m_String = str; // string } StringIdAAR.prototype = BaseAAR.prototype; // innherit from StringIdAAR prototype 

I'm not quite sure if this code really does what you want, but you need to understand how object oriented templates look in JavaScript. If you want to learn more about how to write good JavaScript, you should absolutely get the book "JavaScript: Good Details" by Douglas Crockford.

UPDATE: I also wrote an article on JavaScript object orientation and prototype-based inheritance . It can be interesting for anyone passing here.

+22
source

For a great example of JavaScript inheritance, take a look at the project implementation that describes it in more detail.

Another library offering similar functionality, base2 , but may be redundant for your needs.

Finally, another popular approach that I have used in the past is Module Pattern . See this article for an article as well as a detailed description of the template.

+1
source

Source: https://habr.com/ru/post/894679/


All Articles