如何做JS 单体模式的设计---->>js设计模式<<-------单体模式
1. 单体模式是js中最基本 单最有用的模式之一,非常常用。
单体模式的基本结构如下:
var Person = { name: 'lilu', age:'20', sayHi: function(){ alert('456456'); }, sayBye: function(){ alert('456456'); } }
这个栗子中,所有的成员都可以通过Person进行访问,用点运算符就行。
如:
Person.name = "zczc"; Person.age = "1000"; var hi = Person.sayHI();
我们可以为这个单体对象添加新的成员变量或者方法,意味着这个对象可以被修改。这么做,违背2了面相对象设计的一条原则:---->>类可以被扩展,但不应该被修改<<------。
那么什么才是真正的单体模式?
先看定义:单体是一个用来划分命名空间并将一批相关方法和属性组织在一起的对象,如果它可以被实例化,那么它只能被实例化一次。
对象字面量只是创建单体的方法之一,并非所有对象字面量都是单体。如果它只是用来模拟数组或储存数据,显然不是单体。主要看我们的意图。
2. 单体对象有两部分组成:包含着方法和属性的成员对象自身,以及用于访问它的变量。这个变量同事是全局的。 以便于在网页上任何地方都能访问它所指向的单体对象。虽然说按照定义单体不一定必须是全局的,但是它应该在各个地方都能被访问。由于这些成员只能通过这个单体对象变量进行访问,在某种意义上说,它们被单体对象全在了一个命名空间中。
3.命名空间 的理解
// 声明全局属性 function Hell() { // ..... } // 页面中其他方法 var Hell = $('dakjka'); //Hell 方法在这里被改变
函数中使用var 声明很重要,如果不用,那么变量将被声明为全局属性,因此容易干扰全局命名空间中的其他代码。
改写为如下代码:
var myFun = { Hell: function(){ // code gose here } } var Hell = $('fsfs'); // Nothing was chenged
现在Hell是myFun中的一个方法,不会别全局命名空间中的任何新变量改写。
命名空间还可以进一步分割。 网页上的JS 代码不止有一个来源。除了我们的代码,还有库代码,广告代码之列,这些变量都出现在网页的全局命名空间中。为了防止冲突,我们可以定义一个包含自己所有代码的全局对象。
var MyCode = {};
然后分门别类将自己的代码和数据组织到全局对象的各个对象中:
var MyCode = {}; MyCode.common = { // 一个单体对象,包含公共的方法 } MyCode.Error = { // 用来存储数据 } MyCode.PageHandler = { // 用来操作页面的方法和属性 }
4. 创建私有成员--->>使用私有方法有一个缺点--比较耗费内存,因为每个实例都具有一个方法的副本。
01.用下划线表示私有成员
MyCode.Data = { // 私有成员 _spave:function(str){ return str.replace('''') } // 共有方法 test:function(){ console.log('this is common method') } }
02.使用闭包
var MyCode = function() { return {}; }()
匿名函数返回一个对象,赋给MyCode;
也可以写作:
var MyCode = (function(){ return {}; })()
我们可以摆共有成员添加到作为单体返回的那个对象字面量中
var MyCode.Data = (function(){ return { hell: function(){}; Bye: function(){}; } })();
如果这样写得到的结果跟使用一个对象字面量没有什么区别,那为什么还要加上外层函数包装呢?
原因就在于这个包装函数创建了一个可以用来添加真正的私用成员的闭包。任何声明在这个匿名函数中的变量或者函数都只能被在同一个闭包中声明的其他函数访问。这个闭包在匿名函数执行结束后依然存在,所以在其中声明的变量和函数总是能从匿名函数所返回的对象内部访问。
var MyCode.Data = (function(){ // 私有 var name = "lilu"; var age = "20"; function print(){ console.log(213); } //共有 return { say:function(){ alert(123); }; rel:function(){ alert(4563); } } })
这些在return 中的方法都是共有方法,可以直接方位私有属性,而不用再前面加this. -->这个前缀只用于访问单体对象的公用成员。