js的封装

  1 js中处处是对象,面向对象的第一步当然就是封装了,由于Js中没有类的概念,所以封装起来也比较麻烦,下面介绍两种js的封装。
  2 
  3 1、使用约定优先的原则,将所有的私有变量以_开头
  4 
  5 [javascript] view plain copy
  6 <script type="text/javascript">  
  7        /** 
  8         * 使用约定优先的原则,把所有的私有变量都使用_开头 
  9         */  
 10        var Person = function (no, name, age)  
 11        {  
 12            this.setNo(no);  
 13            this.setName(name);  
 14            this.setAge(age);  
 15        }  
 16        Person.prototype = {  
 17            constructor: Person,  
 18            checkNo: function (no)  
 19            {  
 20                if (!no.constructor == "string" || no.length != 4)  
 21                    throw new Error("学号必须为4位");  
 22            },  
 23            setNo: function (no)  
 24            {  
 25                this.checkNo(no);  
 26                this._no = no;  
 27            }, getNo: function ()  
 28            {  
 29                return this._no;  
 30            }, setName: function (name)  
 31            {  
 32                this._name = name;  
 33            }, getName: function ()  
 34            {  
 35                return this._name;  
 36            }, setAge: function (age)  
 37            {  
 38                this._age = age;  
 39            }, getAge: function ()  
 40            {  
 41                return this._age;  
 42            }, toString: function ()  
 43            {  
 44                return "no = " + this._no + " , name = " + this._name + " , age = " + this._age;  
 45            }  
 46        };  
 47        var p1 = new Person("0001", "鸿洋", "22");  
 48        console.log(p1.toString());        //no = 0001 , name = 鸿洋 , age = 22  
 49        p1.setNo("0003");  
 50        console.log(p1.toString());      //no = 0003 , name = 鸿洋 , age = 22  
 51        p1.no = "0004";  
 52        p1._no = "0004";  
 53        console.log(p1.toString());    //no = 0004 , name = 鸿洋 , age = 22  
 54   
 55    </script>  
 56 看完代码,是不是有种被坑的感觉,仅仅把所有的变量以_开头,其实还是可以直接访问的,这能叫封装么,当然了,说了是约定优先嘛,这种方式还是不错的,最起码成员变量的getter,setter方法都是prototype中,并非存在对象中,总体来说还是个不错的选择。如果你觉得,这不行,必须严格实现封装,那么看第二种方式。
 57 
 58 2、严格实现封装
 59 
 60 [javascript] view plain copy
 61 <script type="text/javascript">  
 62         /** 
 63          *  使用这种方式虽然可以严格实现封装,但是带来的问题是get和set方法都不能存储在prototype中,都是存储在对象中的 
 64          * 这样无形中就增加了开销 
 65          */  
 66         var Person = function (no, name, age)  
 67         {  
 68             var _no , _name, _age ;  
 69             var checkNo = function (no)  
 70             {  
 71                 if (!no.constructor == "string" || no.length != 4)  
 72                     throw new Error("学号必须为4位");  
 73             };  
 74             this.setNo = function (no)  
 75             {  
 76                 checkNo(no);  
 77                 _no = no;  
 78             };  
 79             this.getNo = function ()  
 80             {  
 81                 return _no;  
 82             }  
 83             this.setName = function (name)  
 84             {  
 85                _name = name;  
 86             }  
 87   
 88             this.getName = function ()  
 89             {  
 90                 return _name;  
 91             }  
 92   
 93             this.setAge = function (age)  
 94             {  
 95                 _age = age;  
 96             }  
 97             this.  
 98                     getAge = function ()  
 99             {  
100                 return _age;  
101             }  
102   
103             this.setNo(no);  
104             this.setName(name);  
105             this.setAge(age);  
106         }  
107         Person.prototype = {  
108             constructor: Person,  
109             toString: function ()  
110             {  
111                 return "no = " + this.getNo() + " , name = " + this.getName() + " , age = " + this.getAge();  
112             }  
113         }  
114         ;  
115         var p1 = new Person("0001", "鸿洋", "22");  
116         console.log(p1.toString());        //no = 0001 , name = 鸿洋 , age = 22  
117         p1.setNo("0003");  
118         console.log(p1.toString());      //no = 0003 , name = 鸿洋 , age = 22  
119         p1.no = "0004";  
120         console.log(p1.toString());    //no = 0003 , name = 鸿洋 , age = 22  
121   
122     </script>  
123 
124 看上面的代码,去掉了this.属性名,严格的实现了封装,只能通过getter,setter访问成员变量了,但是存在一个问题,所有的方法都存在对象中,增加了内存的开销。
125 3、以闭包的方式封装
126 
127 [javascript] view plain copy
128 <script type="text/javascript">  
129         /** 
130          *  使用这种方式虽然可以严格实现封装,但是带来的问题是get和set方法都不能存储在prototype中,都是存储在对象中的 
131          * 这样无形中就增加了开销 
132          */  
133         var Person = (function ()  
134         {  
135             var checkNo = function (no)  
136             {  
137                 if (!no.constructor == "string" || no.length != 4)  
138                     throw new Error("学号必须为4位");  
139             };  
140             //共享变量  
141             var times = 0;  
142   
143             return function (no, name, age)  
144             {  
145                 console.log(times++);    // 0 ,1 , 2  
146                 var no , name , age;  
147                 this.setNo = function (no)  
148                 {  
149                     checkNo(no);  
150                     this._no = no;  
151                 };  
152                 this.getNo = function ()  
153                 {  
154                     return this._no;  
155                 }  
156                 this.setName = function (name)  
157                 {  
158                     this._name = name;  
159                 }  
160   
161                 this.getName = function ()  
162                 {  
163                     return this._name;  
164                 }  
165   
166                 this.setAge = function (age)  
167                 {  
168                     this._age = age;  
169                 }  
170                 this.  
171                         getAge = function ()  
172                 {  
173                     return this._age;  
174                 }  
175   
176                 this.setNo(no);  
177                 this.setName(name);  
178                 this.setAge(age);  
179             }  
180         })();  
181         Person.prototype = {  
182             constructor: Person,  
183             toString: function ()  
184             {  
185                 return "no = " + this._no + " , name = " + this._name + " , age = " + this._age;  
186             }  
187         }  
188         ;  
189         var p1 = new Person("0001", "鸿洋", "22");  
190         var p2 = new Person("0002", "abc", "23");  
191         var p3 = new Person("0003", "aobama", "24");  
192   
193   
194         console.log(p1.toString());        //no = 0001 , name = 鸿洋 , age = 22  
195         console.log(p2.toString());      //no = 0002 , name = abc , age = 23  
196         console.log(p3.toString());    //no = 0003 , name = aobama , age = 24  
197   
198     </script>  
199 
200 上述代码,js引擎加载完后,会直接执行Student = 立即执行函数,然后此函数返回了一个子函数,这个子函数才是new Student所调用的构造函数,又因为子函数中保持了对立即执行函数中checkNo(no) ,times的引用,(很明显的闭包)所以对于checkNo和times,是所有Student对象所共有的,创建3个对象后,times分别为0,1,2 。这种方式的好处是,可以使Student中需要复用的方法和属性做到私有且对象间共享。
原文地址:https://www.cnblogs.com/yangguoe/p/8527392.html