JavaScript模拟面向对象
1. 类
//创建一个Person类 var Person= function(name,sex){ this._name = name; this._sex = sex; } //创建一个Person对象 var person = new Person(“狂奔”,’男’); |
2. 私有变量
var Person = function(name,sex){ this._name = name; this._sex = sex;
var _age,_address; //私有变量 this.setAge = function(age){ this_age = age; } this.getAge = function(){ return _age; } ……. } |
3. 公共变量
//创建一个Person类 var Person= function(name,sex,age){ this._name = name; this._sex = sex; this.age = age; //公有变量 } Person.prototype = { country:’中国’, //公共变量 display:function(){ alert(this.country); } } |
4. 静态变量
var Person= function(name,sex,age){ this._name = name; this._sex = sex; Person.country = "中国"; }
//调用静态变量 new Person(); alert(Person.country); |
5. 私有方法
var Person= function(name,sex){ this._name = name; this._sex = sex;
//私有方法 var checkEmail = function(){ return true; } } |
6. 公共方法
var Person= function(name,sex){ this._name = name; this._sex = sex; }
Person.prototype = { //公共方法 add:function(){ alert(“执行【添加】操作!”); } } //调用公共方法 new Person(“狂奔”,”男”).add(); |
7. 静态方法
var Person= function(name,sex){ this._name = name; this._sex = sex;
Person.converToCase = function(_name){ alert("将["+_name+"]转换成大写!"); } } //调用静态方法 new Person(); Person.converToCase(“shangwu”);
|
8. JS 模式私有变量、方法、静态变量、方法、公共变量、方法完整的例子
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>JS 模式私有变量、方法、静态变量、方法、公共变量、方法完整的例子</title> <script type="text/javascript"> var Person = function(_name,_sex){
/********************************************************************************* * 私有属性 *********************************************************************************/ var age,address,phone,email; var checkPhone = function(){ return true; } var checkEmail = function(){ return true; } /********************************* 私有属性 end **********************************/
/********************************************************************************* * 这些属于特权方法,因为他们是公共方法,但可以访问私有属性及私有变量 *********************************************************************************/ //姓名 this.setName = function(_name){ name = _name || 'No name specified'; } this.getName = function(){ return name; }
//性别 this.setSex = function(_sex){ sex = _sex || 'No sex specified'; } this.getSex = function(){ return sex; }
//年龄 this.setAge = function(_age){ age = _age; // || 'No age specified'; } this.getAge = function(){ return age; }
//地址 this.setAddress = function(_address){ address = _address || 'No address specified'; } this.getAddress = function(){ return address; }
//电话 this.setPhone = function(_phone){ phone = _phone || 'No phone specified'; } this.getPhone = function(){ return phone; }
//邮件 this.setEmail = function(_email){ if(!checkEmail(_email)) throw new Error('Book: Invalid ISBN'); email = _email || 'No email specified'; } this.getEmail = function(){ return email; } /****************************特权方法结束****************************************/
/********************************************************************************* * 静态变量、静态方法 *********************************************************************************/ Person.country = "中国"; Person.converToCase = function(_name){ alert("将["+_name+"]转换成大写!"); } /***********************************静态变量、静态方法 end************************/
/********************************************************************************* * 常量:是一些不能被修改的变量, * 在js中,可以通过创建只有取值器而没有赋值器的私有变量来模仿常量。 *********************************************************************************/ var Max = 154; Person.getMax = function(){ return Max; } //若要使用多个常量可以如下: var constants = {UPPER:100,LOWER:-100}; Person.getConstant = function(_name){ return constants[_name]; } /****************************** 常量 end *****************************************/
//构造方法设置属性 this.setName(_name); this.setSex(_sex); }
/********************************************************************************* * 公共属性、方法,不可以访问私有变量、私有方法 *********************************************************************************/ Person.prototype = { display:function(){ var personInfo = "姓名:"+this.getName()+" 性别:"+this.getSex()+" 年龄:" +this.getAge()+" 地址:"+this.getAddress()+" 电子邮件:" + this.getEmail(); alert(personInfo); }, add:function(){ alert('执行[添加]操作!'); }, edit:function(){ alert('执行[编辑]操作!'); }, del:function(){ alert("执行[删除]操作!"); } };
//创建Person实例、设置实例方法、调用实例方法 var p = new Person('狂奔','男'); p.setAge(18); p.setAddress("深圳"); p.setEmail("shenzhen_zsw@163.com"); p.display(); p.add(); p.edit(); p.del();
//调用常量 alert(Person.getMax()); alert(Person.getConstant('LOWER'));
//调用静态变量、静态方法 alert(Person.country); Person.converToCase(p.getName());
</script> </head>
<body> </body> </html> |
9. 接口
/** * name:指的是接口名称 * methods:指的是接口中定义的方法如:["add","edit","del"] */ var Interface = function(name,methods){ if(arguments.length!=2){ throw new Error("接口构造函数包含" + arguments.length + "参数,但必须是是个!"); }
this.name = name; this.methods = []; for(var i = 0, len = methods.length; i < len; i++){ if(typeof methods[i] !== 'string'){ throw new Error("结构构造函数中定义的方法名必须是字符串类型"); } this.methods.push(methods[i]); } };
Interface.ensureImplements = function(object){ if(arguments.length < 2){ throw new Error("Function Interface.ensureImplements called with " + arguments.length + "arguments,but expected at least 2."); } for(var i = 1,len = arguments.length; i<len; i++){ var interface = arguments[i]; if(interface.constructor !== Interface){ throw new Error("Function Interface.ensureImplements expects arguments two and above to be instances of Interface."); }
for(var j = 0,methodsLen = interface.methods.length; j < methodsLen; j++){ var method = interface.methods[j]; if(!object[method] || typeof object[method] !== 'function'){ throw new Error("Function Interface.ensureImplements : object does not implement " +"the interface.name interface.Method" + method + " was not found."); } } } } |
接口使用的例子:
var PiJiu = new Interface('PiJiu',['getDisplay']); var JinWei = function(){ this.name = "金威啤酒"; } JinWei.prototype = { getDisplay : function(){ return "你好,我是["+this.name+"]!"; } }; var QingDao = function(){ this.name = "青岛啤酒"; } QingDao.prototype = { getDisplay : function(){ return "你好,我是["+this.name+"]!"; } }
var PinJiuFactory = function(pjObj){ Interface.ensureImplements(pjObj,PiJiu); this.pj = pjObj; } PinJiuFactory.prototype = { getPiJiu : function(){ var str = this.pj.getDisplay(); alert(str); } };
var qingDaoPJ = new QingDao(); var jinWeiPJ = new JinWei(); var testPj = new PinJiuFactory(qingDaoPJ); testPj.getPiJiu();
testPj = new PinJiuFactory(jinWeiPJ); testPj.getPiJiu(); |
10. 继承
类式继承 – 原型链
function Person(name){ this.name = name; } Person.prototype.getName = function(){ return this.name; }
function Author(name,books){ Person.call(this,name); //调用父类的构造函数,并将name参数传给它 this.books = books; }
/* 设置原型链,JavaScript中每个对象都有一个名为prototype的属性这个属性要么只想另一个对象,要么是null 为了让一个类继承另一个类,只是将子类的prototype设置为指向超类的一个实例。 为了让Author继承Person类,必须手工将Author的prototype属性设置为Person的一个实例。 最后一个步骤是将prototype的constructor属性设置为Person的实例时,其constructor属性被抹除了。 */ Author.prototype = new Person(); Author.prototype.constructor = Author; Author.prototype.getBooks = function(){ return this.books; }
/* * 指的注意的是,在执行Person.call(this,name);这一步的时候我们已经把name * 这个属性拷贝到Person里面了,这里我们不在需要new Person()里面的这个null * 的name,所以直接把他们删除,免得浪费内存 */ delete Author.prototype.name;
var author = new Author("闫宏","Java与模式"); alert(author.getName()); alert(author.getBooks()); |
类式继承 – extend函数
/* 把派生子类的的整个过程包装在一个名为extend的函数中, 它的作用与其他语言中的extend函数类似, 即基于一个给定的类创建一个新对象的类。 实现步骤: 1.设置prototype 2.在将constructor重设置为恰当的值 3.做了一项改进,它添加了一个空函数F,并将用它创建一个对象的实例插入到原型链中。 这样做可以避免创建类的新实例,以为可能会比较庞大,而且有时超类的构造函数有一些副作用, 或者会执行一些需要进行大量计算的任务。 */ function extend(subClass,superClass){ var F = function(){}; F.prototype = superClass.prototype; subClass.prototype = new F(); subClass.prototype.constructor = subClass; }
/*----- extend函数的用法--------*/ function Person(_name){ this.name = _name; } Person.prototype.getName = function(){ return this.name; }
function Author(_name,_books){ Person.call(this,_name); this.books = _books; } extend(Author,Person); Person.prototype.getBooks = function(){ return this.books; }
var author = new Author("闫宏","Java与模式"); alert(author.getName()); alert(author.getBooks());
/* 在这里,不需要手工设置prototype和constructor属性, 而是通过在类声明之后(在向prototype添加任何方法之前)立即调用extend函数, 可以达到同样的目的。 不过还是有一个问题,超类的名称被固有化在子类的声明之中。 下面会对extend进行改进
*/ |
类式继承 – 对extend函数的改进
/* * 在此记录中,他提供了superclass属性,这个属性可以用来用户子类与父类之间的耦合。 * 有了superclass属性,就可以直接调用父类超类中的方法。 * 如果既要重定义超类的某个方法而又想访问其在超类中的实现时可以派上用场) */ function extend(subClass,superClass){ var F = function(){}; F.prototype = superClass.prototype; subClass.prototype = new F(); subClass.prototype.constructor = subClass;
subClass.superclass = superClass.prototype; if(superClass.prototype.construtor == Object.prototype.constructor){ superClass.prototype.constructor = superClass; } }
/*此函数的用法*/ function Person(_name){ this.name = _name; } Person.prototype.getName = function(){ return this.name; }
function Author(_name,_books){ Author.superclass.constructor.call(this,_name); this.books = _books; } extend(Author,Person); Author.prototype.getBooks = function(){ return this.books; }
var test = new Author("闫宏","Java与模式"); alert(test.getName()); alert(test.getBooks()); |