Learn JavaScript Design patterns (encapsulation) _javascript tips

Source: Internet
Author: User
Tags closure naming convention

In JavaScript, there is no support for abstract classes and interfaces. JavaScript itself is also a weakly typed language. JavaScript does not have the ability or need to do more in terms of encapsulation types. For JavaScript design pattern implementations, the distinction between types is a pale, or a relief.

From the point of view of design pattern, encapsulation is reflected in the more important aspect as encapsulation change.

By encapsulating the changes in the system to isolate the stable and easy to change parts of the system, we only need to replace those parts that are easy to change, and if they are already encapsulated, it is relatively easy to replace them. This can maximize the stability and scalability of the program.

The basic patterns of JavaScript encapsulation are 3 kinds:

1, the use of the principle of agreement first, all the private variables to _ start

 <script type= "Text/javascript" >/** * Use the principle of the Convention first, all the private variables are used _ the start/var person = function (no, name, age)
   {This.setno (NO);
   This.setname (name);
  This.setage (age); } Person.prototype = {Constructor:person, checkno:function (NO) {if (!no.constructor = = "string" | | No.
   Length!= 4) throw new Error ("The school number must be 4 bits");
    }, Setno:function (NO) {this.checkno (no);
   This._no = no;
   }, Getno:function () {return this._no;
   Setname:function (name) {this._name = name;
   }, Getname:function () {return this._name;
   }, Setage:function (age) {this._age = age;
   }, Getage:function () {return this._age;
   }, Tostring:function () {return "no = + This._no +", name = "+ This._name +", age = "+ This._age;"
  }
  };
  var p1 = new Person ("0001", "Xiao Guo", "22");  Console.log (P1.tostring ());
  No = 0001, name = fruit, age = P1.setno ("0003"); Console.log (P1. toString ());
  No = 0003, name = Xiao Guo, age = p1.no = "0004";
  P1._no = "0004"; Console.log (P1.tostring ());
 No = 0004, name = Pistachio, age = </script>

Read the code, is not a kind of pit feeling, just put all the variables to _ the beginning, in fact, or can be directly accessed, this can be called Encapsulation Mody, of course, said is the agreement priority.

This use of an underscore is a well-known naming convention that indicates that an attribute is intended for internal use only, accessing it directly or setting it may cause unintended consequences. This helps prevent programmers from unintentionally using it, but does not prevent intentional use of it.

This approach is still good, the minimum membership variable Getter,setter methods are prototype, not the existence of objects, in general, is a good choice. If you feel that this does not work, you must strictly implement the encapsulation, then look at the second way.

2, strict implementation of packaging

<script type= "Text/javascript" >/** * Use this way although encapsulation is strictly implemented, the problem is that both get and set methods cannot be stored in the prototype, and are stored in the object's * so virtually
   Increased overhead */var person = function (no, name, age) {var _no, _name, _age;
   var checkno = function (no) {if (!no.constructor = = "string" | | | no.length!= 4) throw new Error ("The number must be 4-bit");
   };
    This.setno = function (no) {checkno (no);
   _no = no;
   };
   This.getno = function () {return _no;
   } this.setname = function (name) {_name = name;
   } this.getname = function () {return _name;
   } this.setage = function (age) {_age = age;
     } this.
   Getage = function () {return _age;
   } this.setno (no);
   This.setname (name);
  This.setage (age); } Person.prototype = {Constructor:person, tostring:function () {return "no =" + This.getno () + ", Nam
   E = "+ this.getname () +", age = "+ This.getage ();
  }
  }
  ; var p1 = new Person ("0001", "Pinky", "22");  Console.log (P1.tostring ());
  No = 0001, name = fruit, age = P1.setno ("0003");  Console.log (P1.tostring ());
  No = 0003, name = Xiao Guo, age = p1.no = "0004"; Console.log (P1.tostring ());

 No = 0003, name = Pistachio, age = </script>

So this is different from the other patterns of creating objects that we talked about earlier, and in the example above we always use the This keyword when creating and referencing the attributes of an object. In this case, we declare these variables with var. This means that they exist only in the person builder. The Checkno function is also declared in the same way, thus becoming a private method.

The methods needed to access these variables and functions are simply declared in person. These methods are called privileged methods because they are public methods, but they have access to private properties and methods. In order to access these privileged functions outside the object, they are preceded by the keyword this. Because these methods are defined in the scope of the person constructor, they can access the private property. The This keyword is not used when referencing these properties because they are not public. All accessors and assignment methods are changed to refer directly to these properties without this.

Any method that does not require direct access to private properties can be declared in the Person.prototype as originally. Like the ToString () method. Only methods that require direct access to a private member should be designed as a privileged method. However, too many privileged methods can consume too much memory because each object instance contains a new copy of all the privileged methods.

Look at the code above, remove this. property name, strict implementation of encapsulation, only through Getter,setter access to member variables, but there is a problem, all methods exist in the object, increased the cost of memory.

3, in the way of closure package

<script type= "Text/javascript" > var person = (function () {//static method (Shared method) var checkno = function (NO)
   {if (!no.constructor = = "string" | | | no.length!= 4) throw new Error ("The school number must be 4-bit");
   };

    static variable (shared variable) var times = 0;
   Return the constructor. return function (no, name, age) {Console.log (times++);//0, 1, 2 var no, name, age;//Private variable This.setno
     = function (no)//private method {Checkno (no);
    This._no = no;
    };
    This.getno = function () {return this._no;
    } this.setname = function (name) {this._name = name;
    } this.getname = function () {return this._name;
    } this.setage = function (age) {this._age = age;
    } this.getage = function () {return this._age;
    } this.setno (no);
    This.setname (name);
   This.setage (age);

  }
  })(); Person.prototype = {Constructor:person, tostring:function () {return "no. =" + This. _no + ", name =" + This._name + ", age =" + this._age;

  }
  };
  var p1 = new Person ("0001", "Xiao Guo", "22");
  var p2 = new Person ("0002", "abc", "23");


  var p3 = new Person ("0003", "Aobama", "24");  Console.log (P1.tostring ());  No = 0001, name = fruit, age = Console.log (p2.tostring ()); No = 0002, name = ABC, age = Console.log (p3.tostring ());

 No = 0003, name = Aobama, age = </script>

The above code, JS engine loaded, will directly execute person = immediately execute the function, and then this function returns a child function, which is the constructor called by new person, and because the child function has persisted to the immediate execution function checkno (no), The Times reference , (very obvious closure) so for Checkno and times, which is common to all person objects, the times are 0,1,2 when you create 3 objects. The advantage of this approach is that the methods and properties that need to be reused in person are private and shared among objects.

The private members and Privileged members here are still declared in the constructor. The constructor, however, becomes an inline function from the original normal function and is given to the variable person as the return value of the function that contains it. This creates a closure that you can declare in the static private member. A pair of empty parentheses after the outer function declaration is important in that the code executes the function as soon as it is loaded. The return value of this function is another function, which is assigned to the person variable, so that person becomes a constructor. This inner function that is called when the instance is in China. The outer layer function is simply used to create a closure that can be used to store static members.

In this case, Checkno is designed as a static method because it makes no sense to generate a new copy of this method for each instance of person. There is also a static property times that is used to track the total number of calls to the person builder.

The above is the entire content of this article, I hope to help you learn, we can learn more in-depth understanding of the meaning of encapsulation.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.