Recently, I am learning the basics of JavaScript, and I am learning object-oriented programming When you learn how to implement modularity in JavaScript, one of the important points is how to encapsulate private variables.
The main methods to encapsulate private variables are:
- Using constructors
function StringBuilder() { var buffer = []; this.add = function (str) { buffer.push(str); }; this.toString = function () { return buffer.join(''); }; } // The disadvantage of the above method is that every time a new instance is generated, the method in it will generate a new instance, resulting in memory waste. Therefore, the following improvements are made function StringBuilder() { this._buffer = []; } StringBuilder.prototype = { constructor: StringBuilder, add: function (str) { this._buffer.push(str); }, toString: function () { return this._buffer.join(''); } }; // At this time, all instances will share the two methods and will not generate repeatedly // But the problem comes again. The private variables we encapsulate are not private, and can be modified directly outside_buffer,as var sb = new StringBuilder(); sb._buffer = 'hello, sb';
- Use execute now function
var module = (function() { function StringBuilder() { this._buffer = []; } StringBuilder.prototype = { constructor: StringBuilder, add: function (str) { this._buffer.push(str); }, toString: function () { return this._buffer.join(''); } }; function createStringBuilder() { var _sb = new StringBuilder(); return { add: StringBuilder.prototype.add.bind(_sb), toString: StringBuilder.prototype.toString.bind(_sb) }; } return { createStringBuilder: createStringBuilder }; })(); console.log(module); // { createStringBuilder: [Function: createStringBuilder] } var sb = module.createStringBuilder(); sb.add('hello'); sb.add('A rookie who loves programming'); console.log(sb.toString()); // hello A rookie who loves programming
In the immediate execution function, the focus is on the function of createStringBuilder, which implements the internal and external docking interfaces, protects the private members of StringBuilder internally, provides the external interfaces to be accessed, and realizes the real private variable encapsulation. Let's use a simple example to compare the above three ways:
// Constructor, var1 It can't be modified by the outside world, but every instance generated, fn Will be copied function Class1() { var var1 = 10; this.fn = function() { console.log(var1); var1 += 1; }; } var c10 = new Class1(); var c11 = new Class1(); console.log(c10.var1); // undefined,Variable not accessible console.log(c10 === c11); // false c10.fn(); // 10 c11.fn(); // 10 c10.fn(); // 11 c11.fn(); // 11 // Improve it function Class2() { this._var1 = 10; } Class2.prototype = { constructor: Class2, fn: function() { console.log(this._var1); this._var1 += 1; } }; var c20 = new Class2(); var c21 = new Class2(); c20.fn(); // 10 c20.fn(); // 11 c21.fn(); // 10 c21.fn(); // 11 console.log(c20._var1); // 11,Variable accessible console.log(c20.fn === c21.fn); // true // To solve the above problems var m = (function() { function Class3() { this.var1 = 10 } Class3.prototype = { constructor: Class3, fn: function() { console.log(this.var1); this.var1 += 1; } }; function createClass3() { var c3 = new Class3(); return { fn: Class3.prototype.fn.bind(c3) }; } return { createClass3: createClass3 } })(); var c30 = new m.createClass3(); var c31 = new m.createClass3(); c30.fn(); // 10 c30.fn(); // 11 c31.fn(); // 10 c31.fn(); // 11