在六月份找工作中,被问的最多的问题就是: 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 //继承的好处:父类新加的功能,子类也具备该功能,子类新加的功能不会影响父类的功能