基础知识
约定:在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 }