JavaScript 设计模式系列:基础知识

   基础知识

  约定:在JavaScript业界,如果变量和方法是使用下划线,则表示该变量和方法是私有方法,只允许内部调用,第三方不应该去调用。

  1>>双重“非”操作返回的是布尔型的数据:

    var bool = !!num;

  2>>函数是一等对象:

  1:匿名函数

    

1  function(){...}

  2:立即调用的匿名函数:

1 (function(){//立即调用的匿名函数
2      var foo = 10;
3      var bar = 2;
4      alert(foo * bar);
5 })();

  3:从外部传值的立即调用的匿名函数:

1 (function(foo,bar){
2      alret(foo * bar);
3 }(10,2);

  4:将立即调用的匿名函数的返回值赋给一个变量:

1 var baz = (function(foo,bar){
2     return foo * bar;
3 })(10,2)

   5:创建闭包:

1 var baz;
2 (function(){
3      var foo = 10;
4      var bar = 2;
5      baz = function(){
6            return foo * bar;
7      };
8 })();
9 baz();

 

闭包:

  1. 最常用的方法是在函数内部返回一个函数,这个返回的函数可以访问内部变量。

      2. 主要就是上一点提到的读取函数内部变量,还有一个作用就是可以使这些变量一直保存在内存中。

如:变量n一直保存在内存中,每执行一次函数,就继续+1。

 1 function  f(){
 2      var n =100;
 3      function f1(){
 4       alert(n+=1);
 5   }
 6 return f1;
 7 }
 8 var result = f();
 9 result();//101
10 result();//102
11 result();//103

 

3>>封装:

 

继承:有两种继承方式

原型继承:通过将对象赋给函数的原型,然后将这个函数返回给一个对象。这样这个初始的对象就获得了开始时的那个对象的属性和方法,实现了继承。

 

//clone用来创建新的类Person对象
var clone = function(obj){
  var f = function(){};
  //**函数的原型对象是对象字面量,即函数的原型里有obj对象的属性和方法
  f.prototype = obj;
  return f;
}
//定义的对象字面量
var Person = {
  name:'free',
  getName:function(){
    return this.name;
  }
}
//创建子类 ,创建的继承对象可以调用父类的方法
var Programmer = clone(Person);
//继续继承
var Someone = clone(Programer);

 

类式继承:  1.构建子类构造函数,同时将需要处理的参数传给父类构造函数。

       2.将父类的实例赋给子类的原型。

       3.修正子类的constructor属性。constructor属性指向构造函数属性,这里是 Person,修正为Programmer

 

 1 //构造函数,相当于超类
 2 function Person(name){
 3       this.name = name;
 4 }
 5 //原型上加方法
 6 Person.prototype.getName = function(){
 7       return this.name;
 8 }
 9 //实例化这个超类
10 var a = new Person('free');
11 alert(a.getName());//free
12 
13 //再声明类,子类  
14 function Programmer(name,sex){
15     //这个类要调用Person的构造函数,并将参数传进去
16     Person.call(this,name);
17     this.sex = sex;
18 }
19 //子类的原型对象等于超类的实例
20 Programmer.prototype = new Person();
21 //修正constructor属性,最终需要指向Programmer。
22 Programmer.prototype.constructor = Programmer;
23 
24 Programmer.prototype.getSex = function(){
25      return this.sex;
26 }
27 
28 var test = new Programmer('free','male');
29 alert(m.getSex());//male
30 alert(m.getName());//free

 4>>接口:提供了一种用以说明一个对象应该具有哪些方法的手段。但并不规定这些方法应该如何实现。

  既定的一批接口具有自我描述性,并能促进代码重用。接口可以告诉我们一个类实现了哪些方法,从而帮助其使用这个类。有利于测试和调试!可以很快发现类型错误。

  实现一:用注释描述接口:在实现接口的方法时加入注释,没有验证!

 1 interface Composite{//接口一
 2   function add(child);
 3   function remove(child);
 4   function getChild(index);
 5 }
 6 
 7 interface FormItem{//接口二
 8   function svae();
 9 }
10 //创建类
11 var CompositeForm = function(id,method,action){
12   ...
13 };
14 //实现接口中的方法
15 CompositeForm .prototype.add = function(child){
16   ...
17 };
18 
19 CompositeForm .prototype.remove= function(child){
20   ...
21 };
22 
23 CompositeForm .prototype.getChild= function(index){
24     ...
25 };
26 
27 CompositeForm .prototype.save= function(){
28   ...
29 };

  实现二:用属性检查模仿接口:所有的类都明确声明自己实现了那些接口,通过检查一个属性的值某个类自称实现了的接口。

 1  interface Composite{//接口一
 2    function add(child);
 3    function remove(child);
 4    function getChild(index);
 5  }
 6  
 7  interface FormItem{//接口二
 8    function svae();
 9  }
10 
11 //声明类 实现了的接口
12 var CompositeForm = function(id,method,action){
13        this.implementsInterfaces = ['Composite','FormItem'];
14 };
15 
16 function addForm(formInstance){
17        if(!implements(formInstance,'Composite','FormItem'){
18                throw new Error("wrong!!");
19         }
20 }
21 
22 function implements(object){
23        for(var i =1,i<arguments.length;i++){
24               var interfaceName = arguments[i];
25               var interfaceFound = false;
26               for(var j=0;j<object.implementsInterfaces.length;j++ ){
27           if(object.implementsInterfaces[j] == interfaceName){
28             interfaceFound = true;
29                      break;
30           }                      
31 
32          }
33         if(!interfaceFound){
34           return false;
35         }
36        }
37     return true;
38 }

  通过调用addForm传入需要检查的对象,然后调用implements方法检查对象是否实现接口,只检查名称,没有检查对应的方法。

   

  实现三:鸭式辩型模仿接口:类是否声明支持那些接口并不重要,只要它具有这些接口中的方法就行。

 1 //接口一
 2 var Composite = new Interface('Composite',['add','remove','getChild']);
 3 //接口二
 4 var FormItem = new Interface('FormItem',['svae']);
 5 
 6 //实现接口的类
 7 var CompositeForm = function(id,method,action){
 8       ...
 9 };
10 //检验接口的方法
11 function addForm(formInstance){
12        ensureImplements(formInstance,Composite,FormItem);
13        ...
14 }

 

首先定义一个Interface类,然后在Interface类中定义ensureImplements方法!

Interface()类用于生成接口

 1 //定义接口
 2 var Interface = function(name,methods){
 3   if(arguments.length != 2){//参数个数必须要大于两个
 4     throw new Error("wrong1!!");
 5   }
 6   this.name = name;
 7   this.methods = [];
 8   for(var i = 0,len = methods.length;i<len;i++){
 9     if(typeof methods[i] !== 'string'){//方法不是字符串,报错
10       throw new Error("wrong2!!");
11       }
12     this.methods.push(methods[i]);//将方法压入到this.methods数组中
13   }
14 };

 

  ensureImplements方法用于确认方法被实现!

 1 Interface.ensureImplements = function(object){
 2   if(arguments.length <2){//检查参数个数
 3     throw new Error("wrong3");
 4   }
 5   //检查参数个数
 6   for(var i =1,len = arguments.length;i<len;i++){
 7     var interface = arguments[i];
 8     if(interface.constructor !== Interface){
 9       throw new Error("wrong4");
10     }
11     for(var j = 0,methodsLen = interface.methods.length;j<methodsLen){
12       var method = interface.methods[j];
13       //检查方法类型和方法是否存在
14       if(!object[method] || typeof object[method] !== 'function'){
15         throw new Error("wrong5");
16       }
17     }
18   }
19 }

 

 

 

 

 

 

posted on 2014-06-22 14:56  color_story  阅读(195)  评论(0编辑  收藏  举报

导航