首页 > 代码库 > JS面向对象(封装,继承)

JS面向对象(封装,继承)

在六月份找工作中,被问的最多的问题就是: js面向对象,继承,封装,原型链这些,你了解多少?

额,,,我怎么回答呢, 只能说,了解一些,不多不少,哈哈哈哈,当然,这是玩笑话。

不过之前学过java,来理解这些还是很容易的。

所以趁着自己空闲的时间,理一理,,这些,,

一、封装

1.原始方法

 1 // 通过new关键字生成一个对象,然后根据javascript是动态语言的特性来添加属性和方法,构造一个对象。其中this表示调用该方法的对象。
 2     var obj = new Object();
 3     obj.name = ‘jessie‘;
 4     obj.age = 22;
 5     obj.showName = function(){
 6         alert(this.name);
 7     };
 8     obj.showAge = function(){
 9         alert(this.age);
10     }
11     obj.showName(); //jessie
12     obj.showAge(); // 22
13     // 这种方式的问题是如果需要多次创建对象,那么需要重复代码多次,不利于代码的复用。

2.工厂模式

 1 function createBlog(name, url) {
 2         var obj = new Object();
 3         obj.name = name;
 4         obj.url = url;
 5         obj.sayName = function(){
 6             alert(this.name);
 7         };
 8         obj.sayUrl = function() {
 9             alert(this.url);
10         };
11         return obj;
12     }
13     var blog1 = createBlog(‘jessie‘, ‘http://www.cnblogs.com/xiayu25/‘);
14     var blog2 = createBlog(‘cuit‘, ‘http://www.cuit.edu.cn‘);
15     blog1.sayName(); // jessie
16     blog1.sayUrl(); // http://www.cnblogs.com/xiayu25/
17     blog2.sayName(); // cuit
18     blog2.sayUrl(); // http://www.cuit.edu.cn
19 
20     // 通过定义几个函数的对象,解决了不同对象持有函数对象的私有属性问题。
21     // 现在所有对象的方法都持有上面两个函数的引用,
22     // 但这么一来,对象的函数又和对象相互独立了,这和面向对象中持有方法属于与特定类的思想不符。
23     // 可以看到工厂模式的实现方法非常简单,解决了创建多个相似对象的问题,
24     // 但是工厂模式却无从识别对象的类型,因为全部都是Object,不像Date、Array等,因此出现了构造函数模式。

3.构造函数模式

 1 function Blog(name, url){
 2         //var this=new Object();  //系统模拟创建对象
 3         this.name = name;
 4         this.url = url;
 5         this.sayName = function(){
 6             alert(this.name);
 7         };
 8         this.sayUrl = function(){
 9             alert(this.url);
10         };
11     }
12     var blog1 = Blog(‘jessie‘, ‘http://www.cnblogs.com/xiayu25/‘);
13     var blog2 = Blog(‘cuit‘, ‘http://www.cuit.edu.cn‘);
14     blog1.sayName(); // jessie
15     blog1.sayUrl(); // http://www.cnblogs.com/xiayu25/
16     blog2.sayName(); // cuit
17     blog2.sayUrl(); // http://www.cuit.edu.cn
18     // 这个例子与工厂模式中除了函数名不同以外,细心的童鞋应该发现许多不同之处:
19     // 函数名首写字母为大写(虽然标准没有严格规定首写字母为大写,但按照惯例,构造函数的首写字母用大写)
20     // 没有显示的创建对象
21     // 直接将属性和方法赋值给了this对象
22     // 没有return语句
23     // 使用new创建对象
24     // 能够识别对象(这正是构造函数模式胜于工厂模式的地方)
25     // 构造函数虽然好用,但也并非没有缺点
26     // 构造函数的方式与工厂加工方式一样,会为每个对象创建独享的函数对象,
27     // 当然也可以将这些函数对象定义在构造函数外面,这样又有了对象和方法相互独立的问题

4.原型模式

 1 function Blog() {}
 2     Blog.prototype.name = ‘jessie‘;
 3     Blog.prototype.url = ‘http://www.cnblogs.com/xiayu25/‘;
 4     Blog.prototype.friend = [‘fr1‘, ‘fr2‘, ‘fr3‘, ‘fr4‘];
 5     Blog.prototype.alertInfo = function() {
 6         alert(this.name + this.url + this.friend );
 7     };
 8     
 9     var blog1 = new Blog(), blog2 = new Blog();
10     blog1.alertInfo();  // jessiehttp://www.cnblogs.com/xiayu25/fr1,fr2,fr3,fr4
11     blog2.alertInfo();  // jessiehttp://www.cnblogs.com/xiayu25/fr1,fr2,fr3,fr4
12     blog1.name = ‘test1‘;
13     blog1.url = ‘http://***.com‘;
14     blog1.friend.pop();
15     blog2.name = ‘test2‘;
16     blog2.url = ‘http://+++.com‘;
17     blog1.alertInfo();  // test1http://***.comfr1,fr2,fr3
18     blog2.alertInfo();  // test2http://+++.comfr1,fr2,fr3
19     // 上面的代码通过blog1向blog1的属性friend添加元素时,
20     // blog2的friend属性的元素也跟着受影响,原因是在于blog1和blog2对象的friend属性引用的是同一个Array
21     // 对象,那么改变这个Array对象,另一个引用Array对象的属性自然也会受到影响

5.混合模式(原型模式 + 构造函数模式)

 

 1 function Blog(name, url, friend) {
 2         this.name = name;
 3         this.url = url;
 4         this.friend = friend;
 5     }
 6 
 7     Blog.prototype.alertInfo = function() {
 8         alert(this.name + this.url + this.friend);
 9     };
10 
11     var blog1 = new Blog(‘jessie‘, ‘http://www.cnblogs.com/xiayu25/‘, [‘fr1‘, ‘fr2‘, ‘fr3‘]),
12             blog2 = new Blog(‘cuit‘, ‘http://www.cuit.edu.cn‘, [‘a‘, ‘b‘]);
13 
14     blog1.friend.pop();
15     blog1.alertInfo();  // jessiehttp://www.cnblogs.com/xiayu25/fr1,fr2
16     blog2.alertInfo();  // cuithttp://www.cuit.edu.cna,b
17 
18     //属性私有后,改变各自的属性不会影响别的对象。
19     // 同时,方法也是由各个对象共享的。在语义上,这符合了面向对象编程的要求。

6.动态原型模式

动态原型模式将所有信息封装在了构造函数中,而通过构造函数中初始化原型(仅第一个对象实例化时初始化原型),这个可以通过判断该方法是否有效而选择是否需要初始化原型。

 1 function Blog(name, url) {
 2         this.name = name;
 3         this.url = url;
 4 
 5         if (typeof this.alertInfo != ‘function‘) {
 6             // 这段代码只执行了一次
 7             alert(‘exe time‘);
 8             Blog.prototype.alertInfo = function() {
 9                 alert(thia.name + this.url);
10             }
11         }
12     }
13 
14     var blog1 = new Blog(‘jessie‘, ‘http://www.cnblogs.com/xiayu25/‘),
15             blog2 = new Blog(‘cuit‘, ‘http://www.cuit.edu.cn‘);
16     // 可以看到上面的例子中只弹出一次窗,‘exe time‘,即当blog1初始化时,
17     // 这样做blog2就不在需要初始化原型,对于使用这种模式创建对象,可以算是perfect了。

 

二、继承(主要是方法的继承和属性的继承)

 1 function person(name, sex){
 2         this.name=name;
 3         this.sex=sex;
 4     }
 5     person.prototype.showName=function(){
 6         alert(this.name);
 7     };
 8     person.prototype.showSex=function(){
 9         alert(this.sex);
10     };
11 
12     function worker(name,sex,job){
13         person.call(this,name,sex);//构造函数伪装   调用父级的构造函数--为了继承属性
14         this.job=job;
15     }
16     //原型链  通过原型来继承父级的方法
17     for(attr in person.prototype){
18         worker.prototype[attr]=person.prototype[attr];
19     }
20     worker.prototype.showJob=function(){
21         alert(this.job);
22     };
23 
24     var op=new person(‘blue‘,‘女‘);
25     var ow=new worker(‘blue‘,‘女‘,‘程序员‘);
26     op.showName();  //blue
27     op.showSex();  //
28     ow.showName();  //blue
29     ow.showSex();  //
30     ow.showJob();  //程序员
31 
32     //继承的好处:父类新加的功能,子类也具备该功能,子类新加的功能不会影响父类的功能

 

JS面向对象(封装,继承)