JavaScript提高篇之面向对象之单利模式工厂模型构造函数原型链模式
1.单例模式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>面向对象之单例模式</title> 6 </head> 7 <body> 8 9 <script type="text/javascript"> 10 //对象数据类型的作用: 11 //把描述同一个事物(同一个对象)的属性和方法放在同一个内存空间下,起到了分组的作用, 12 //这样不同的事物之间的属性即使属性名相同,相互也不会冲突。 13 //--->我们把这种分组编写代码的模式叫做“单例模式” 14 //--->在单例模式中我们把person1或者person2也叫做命名空间。 15 16 var person1={ 17 name:"lizebo", 18 age:23 19 }; 20 var person2={ 21 name:"liutinghhh", 22 age:22, 23 }; 24 console.log("========="); 25 console.log(person1.name); 26 console.log(person2.name); 27 28 29 //单例模式是一种项目开发中经常使用的模式,因为项目中我们可以使用单例模式进行“模块开发” 30 //“模块开发:”相对一个来说比较大的项目,需要多人写作的开发,我们一般下会根据当前项目的需求划分成几个功能模块,每个人负责一部分,同时开发, 31 //最后把代码合在一起。 32 </script> 33 </body> 34 </html>
2.工厂模式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>工场模式</title> 6 </head> 7 <body> 8 9 <script type="text/javascript"> 10 var jsPerson1={ 11 name:"walihong", 12 age:48, 13 writeJs:function () { 14 console.log("my name is"+this.name+",i can write javascript"); 15 } 16 }; 17 jsPerson1.writeJs(); 18 console.log("========工厂设计模式======") 19 //单例设计模式是手工作业模式,虽然解决了分组的作用,但是不能实现批量生产,属于手工作业模式-->这就出现了工厂模式:顾名思义,就是批量生产。 20 //工厂模式就是把实现同一件事情的代码放到一个函数中,以后如果在想实现这个这个功能,不需要从新的编写这些代码来了,只需要执行当前的函数即可。 21 //工厂模式有一个专业的名词,“函数的封装”。--->低耦合,高内聚,减少页面中的冗余代码,提高代码的重复利用率。 22 function createJsPerson(name,age) { 23 var obj={}; 24 obj.name=name; 25 obj.age=age; 26 obj.writeJs=function () { 27 console.log("my name is"+this.name+",i can write javascript"); 28 } 29 return obj; 30 } 31 var personDemo1=createJsPerson("lizbeo",234); 32 personDemo1.writeJs(); 33 //这样上面的方法就可以批量生产! 34 //js是一门轻量级的脚本“编程语言”(HTML+CSS不属于编程语言,属于标记语言) 35 //继承:子类继承父类中的属性和方法 36 //多态:当前的函数的多种形态 37 //在后台语言中:多态包含重载和重写 38 39 //JS中不存在重载,方法名一样的话,后面的会把前面的覆盖掉,最后只保留一个。 40 //为什么js面向对象但是有没有重载呢? 41 //1.高阶层次,在js中,存在预解释机制(js中特有的机制),它只会申明函数一次,如果遇到了 42 //与函数名字相同,那么它不会再次申明和定义,只会重新赋值。 43 //2.在函数的层次,在js函数中,所有的函数的参数都用一个类似数组的arguments接收,这个argument接收一切参数, 44 //即使你传入的参数比定义时候的参数多,那么它也就收并且值为undefined,而不会报错,这也间接证明了没有重载。 45 46 //js中有重写:子类重写父类的方法......未完待续!!! 47 48 49 </script> 50 </body> 51 </html>
3.构造函数模式基础
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>构造函数模式基础</title> 6 </head> 7 <body> 8 <script type="text/javascript"> 9 //构造函数模式的目的就是为了创建一个自定义类,并且创建这个类的实例。 10 //========工厂模式例======== 11 function creatFactor(name,age){ 12 var obj={}; 13 obj.name=name; 14 obj.age=age; 15 obj.methodFactoryMethod=function () { 16 console.log("my name is "+this.name+",my age is "+this.age+",在学JavaScript") 17 } 18 return obj; 19 //如果把var obj={} 和return obj去调用,并且把obj换成this,那么就变成了类;那么我们执行的时候,如果 20 // 使用var demo=createFactor("李泽",23);这是普通方法执行,由于没有返回值;所以 21 // 结果是undefined。那么this这里指的又是什么呢?由于没有人调用,这个this就是指的是 22 // window这个对象。。 23 24 // 而在使用new 之后,结果就返回了一个对象;为什么,简单说浏览器执行到这儿的时候, 25 // 一看到new这个关键字,他会自动创建一个对象并且返回,这是我们看不到的,所以我们可以 26 // 使用var demo来进行接收。 27 } 28 var demo=creatFactor("lizbeo",23); 29 demo.methodFactoryMethod(); 30 31 //构造函数模式和工厂模式的区别? 32 //1.执行的时候 33 //普通函数执行-->creatFactor(); 34 //构造函数模式:-->new creatFactor(); 35 //通过new执行,我们的creatFactor就是一个类了。参照js内置类的命名方式,类的第一个首字母大写。 36 //而函数执行的返回值p1就是creatFactor这个类的一个实例 37 //2.函数代码执行的时候 38 //相同点:都是形成一个私有作用域,然后经历形式参数赋值-->预解释--->代码从上到下执行(类和普通函数一样,它有普通函数的一面)。 39 //不同点:在代码执行之前,不用手动创建对象了,浏览器会默认创建对象数据类型的值。 40 // (这个对象其实就是当前类的一个实例) 41 // 接下来代码从上到下执行,以当前的实例执行的主体(this代表的是当前的实例), 42 // 然后分别把属性名和属性值赋值给当前的实例。 43 // 最后浏览器会默认的把创建的实例返回。 44 console.log("=============") 45 //不需要在手动创建返回的对象,浏览器会将默认的对象返回,我们只需要定义一个var进行接收。 46 var p1=new creatFactor("liuhuan",23); 47 p1.methodFactoryMethod(); 48 49 console.log("========数组实例:=========") 50 //比如创建一个数组: 51 // 字面量方式 52 var ary=[]; 53 // 实例创建方式-->构造函数执行模式的方式。 54 var ary1=new Array(); 55 //不管哪一种方式,ary都是Array这个类的一种实例 56 57 //1.*js中所有的类都是函数数据类型的,它通过new 执行变成了一个类,但是他本身也是一个普通的函数。---优点跟Java不一样,js直接把类归在了函数数据类型中。 58 //js中所有的实例都是对象数据类型的, 59 60 //2.*****this的第4种用法*******在构造函数模式中,类中(函数体中)出现的this.xxx=xxx中的this是当前类的一个实例。 61 62 var p2=new creatFactor("WangXi",48); 63 //这里的p2是createFactor类的另外一个实例 64 console.log("================"); 65 p2.methodFactoryMethod(); 66 //3.p1和p2都是creatFactor这个类的实例,所以都拥有writeJS这个方法,但是不同实例之间的方法是不一样的。 67 //在类中给实例增加的属性(this.xxx=xxx)属于当前实例的私有属性,实例与实例之间是单独的个体,所以私有属性不是同一个,是不相等的。 68 console.log(p1.methodFactoryMethod===p2.methodFactoryMethod);//flase 69 </script> 70 </body> 71 </html>
4.构造函数模式扩展
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>构造函数扩展</title> 6 </head> 7 <body> 8 9 <script type="text/javascript"> 10 function Fn() { 11 this.x=100; 12 this.getX=function () { 13 console.log(this.x); 14 } 15 } 16 var f1=new Fn; 17 //1.在构造函数模式种,new Fn()执行,如果Fn种不传递参数,()可以省略。 18 //2.this的问题:在类种出现的this.xxx=xxx中的this都是当前类的实例。而某一属性值(方法),方法中的this需要看方法执行的时候,前面是不是有"." 19 //才能知道this所指。 20 f1.getX();//--->方法中的this是f1-->100 21 var ss2=f1.getX; 22 ss2();//方法中的this是window-->undefined 23 24 console.log("=========例子2:=========="); 25 function Fn1(){ 26 var num=10; 27 this.x=100; 28 this.getx=function () { 29 console.log(this.x); 30 } 31 } 32 var f1=new Fn1; 33 console.log(f1.num);//undefined 34 console.log("=========例子3======="); 35 36 function Fn3() { 37 var num=109; 38 this.x=100; 39 this.getX=function () { 40 console.log(this.x); 41 } 42 return 100; 43 } 44 var f3=new Fn3; 45 console.log(f3); 46 //4.在构造函数模式中浏览器会把我们的实例返回(返回的是一个对象数据类型的值);如果我们自己手动写了return返回; 47 //返回的是一个基本的数据类型的值,当前实例是不变的,列如:return 100; 48 //我们的f3还是当前Fn3类的实例 49 //返回的是一个引用数据类型的值,当前的实例会被自己返回的值给替换掉,列如: 50 //return(name:"哈哈")我们的f3就不再是Fn3的实例了,而是对象{name:"哈哈"}; 51 52 //5.检测某一个实例是否属于一个类-->instanceof 53 console.log(f3 instanceof Fn3);//--->true; 54 console.log(f3 instanceof Array);//---->false; 55 console.log(f3 instanceof Object);//---->true;因为所有的实例都是Object类型的 56 //而每一个对象数据类型都是Object这个内置类的一个实例,为啥这样?未完待续!!!! 57 console.log("========================") 58 //对于检测数据类型来说,typeof有自己的局限性,不能区分Object下的对象,数组,正则。 59 var a=[]; 60 console.log(a instanceof Array);//-->true 61 //6.检测共有属性。 62 var f4=new Fn3; 63 var f5=new Fn3; 64 //in:检测某一个属性是否属于这个对象 attr in object,不管是私有的还是公有的属性,只要存在,用in 来检测都是true 65 console.log("getX" in f5);//-->true 是它的一个属性。 66 //hasOwnProperty:用来检测某一个属性是否为对象的“私有属性”,这个方法只能检测私有的属性 67 console.log(f5.hasOwnProperty("getX"));//--->true "getX"是f5的私有属性。 68 69 //思考:检测一个属性是否是对象的“公有属性” hasGongYou方法 70 function hasGongYou方法 (obj,attr) { 71 if(attr in obj){ 72 if(jianCe.hasOwnProperty(attr)){ 73 return true; 74 } 75 } 76 else { 77 return false; 78 } 79 } 80 var jianCe={name:"lizbeo"}; 81 var zhenJia=hasGongYou方法(jianCe,"name") 82 console.log("====================") 83 console.log(zhenJia) 84 //简写 85 function hasPubProperty(object1,attr) { 86 return (attr in object1) && !object1.hasOwnProperty(attr); 87 } 88 var jianCe1={name:"lizbeo"}; 89 var zhenJia1=hasGongYou方法(jianCe1,"name") 90 console.log("===========") 91 console.log(hasPubProperty(jianCe1,"name")) ; 92 93 //7.isPrototypeOf 94 </script> 95 </body> 96 </html>
5原型链模式基础
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>15原型链模式基础</title> 6 </head> 7 <body> 8 9 10 <script type="text/javascript"> 11 // 1.类例子回顾--构造函数模式 12 13 console.log("===============原型链的引出======================") 14 function createDemo(name,age) { 15 this.name=name; 16 this.age=age; 17 this.writeJs=function () { 18 console.log("my name is"+this.name+",i can write Js"); 19 }; 20 } 21 var p1=new createDemo("liuhze",234); 22 var p2=new createDemo("liuhuan",25); 23 console.log(p1.writeJs===p2.writeJs);//false; 24 //构造函数拥有了类和实例的概念,并且类和实例之间是相互独立开的-->实例识别。 25 // 2.可不可以让私有的writeJs方法,成为共有的呢?也就是说,我们实例化2个对象p1和p2他们有公有的方法 26 function createDemo2(name,age) { 27 this.name=name; 28 this.age=age; 29 createDemo2.prototype.writeJs=function () { 30 console.log("my name is"+this.name+", i can write JS "); 31 }; 32 } 33 var p3=new createDemo2("李强",23); 34 var p4=new createDemo2("刘华",26); 35 console.log(p3.writeJs===p4.writeJs);//这样结果就是true了,这2个实例调用了公有的方法。 36 //基于构造函数模式的原型模式解决了 方法或者属性公有的问题-->把实例之间相同的属性和方法提取成公有的属性和方法---》 37 //想让谁公有就把它放在createJsPerson.prototype上即可。 38 39 console.log("=====================原型链==============================="); 40 41 //1.每一个函数数据类型(普通函数,类)都有一个天生的自带属性:prototype(原型),并且这个属性是一个对象数据类型的值 42 //2.并且在prototype上浏览器天生给它加了一个属性constructor(构造函数),属性值是它当前函数(类)本身。 43 //3.每一个对象数据类型(普通的对象,实例,prototype)也天生自带一个属性:__proto___, 44 //这个属性值是当前实例所属类的原型(prototype)。 45 46 function Fn() { 47 this.x=100; 48 Fn.prototype.getX=function () { 49 console.log(this.x); 50 } 51 } 52 var f1=new Fn(); 53 var f2=new Fn(); 54 console.log(f1.getX===f2.getX);//true 55 console.log(Fn.prototype.constructor);//结果是函数Fn的代码字符串!!! 56 //原理见图原型链1.png 57 console.log(Fn.prototype.constructor===Fn);//true 58 // 2 .Object是所有JS中所有对象数据类型的父类(最顶层的类) 59 //1).f1 instanceof Object-->true因为f1通过__proto__可以想上级查找 60 //不管有多少级,最后总能找到Object. 61 //2).在Object.prototype上没有__proto__这个属性, 62 63 // 3.原型链模式 64 //f1.hasOwnProperty("x");hasOwnProperty是f1的一个属性 65 //但是我们发现在f1的私有属性上并没有这个方法,那如何处理呢? 66 //通过 对象名.属性名获取属性值的时候,首先在对象的私有属性上进行查找,如果私有的属性存在这个属性则 67 //获取的是私有属性值; 68 //如果私有属性没有,则通过__proto__找到所属类的原型(类的原型上定义的属性和方法都是当前实例的公有的属性和方法), 69 //原型上存在的话,获取公有的属性值; 70 //如果原型上也没有,则继续通过原型上的__proto___继续向上查找。一直找到Object.prototype为止。 71 //这种查找机制就是我们的“原型链模式” 72 73 // 练习题 74 console.log("===========原型链的练习题=========="); 75 var tf1=f1.getX===f2.getX;//---->true 76 console.log(tf1); 77 console.log(f1.__proto__.getX===f2.getX);//--->true 78 console.log(f1.getX===Fn.prototype.getX);//--->true; 79 80 console.log(f1.hasOwnProperty===f1.__proto__.__proto__.hasOwnProperty);//true; 81 //在IE浏览器中,我们原型模式也是同样的原理,但是IE浏览器怕你通过__proto__把公有的修改,禁止使用__proto__. 82 //IE浏览器会有保护机制,所以不让你通过__proto__一直修改属性,他会提示这个属性不存在。 83 </script> 84 </body> 85 </html>
6.原型链模式扩展-this和原型扩展
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>课时16:原型链模式扩展-this和原型扩展</title> 6 </head> 7 <body> 8 9 <script type="text/javascript"> 10 //在原型模式中,常用的有2中情况: 11 //在类中this.xxx=xxx;this--->当前累的实例 12 //在某一个方法中this--->看执行的时候,”."前面是谁,就是谁。 13 //1)需要先确定this的指向(this是谁) 14 //2)吧this替换成对应的代码 15 //3)按照原型链查找机制,一步步查找数值。 16 function Fn() { 17 this.x=100; 18 this.y=100; 19 this.getY=function () { 20 console.log(this.y); 21 }; 22 } 23 Fn.prototype={ 24 constructor:Fn, 25 y:300, 26 getX:function () { 27 console.log(this.x); 28 }, 29 getY:function () { 30 console.log(this.y); 31 } 32 } 33 34 35 var f=new Fn; 36 f.getX();//执行的是公有属性中的getX()方法,先去找私有的,没有去找公有的。100 37 //-->执行步骤:console.log(f.x)-->100 38 //f.__proto__.getx();//结果是undefined,有意思吧。 39 //this是f.__proto__--->f.__proto__.x-->没有x的值,再去找Object的值,没有所以undefined。 40 // 练习题 41 Fn.prototype.getX();//---->undefined 42 f.getY();//---->200; 43 // f.__proto__.getY();f//---->300; 44 console.log("========数组实现内置方法去重======") 45 Array.prototype.myUnique=function () { 46 //this---> 47 console.log("这是原型链中公有的方法,使用ary.myUnique执行的是公有方法!") 48 var obj={}; 49 for(var i=0;i<this.length;i++){ 50 var cur=this[i]; 51 if(obj[cur]==cur){ 52 this[i]==this[this.length-1]; 53 this.length--; 54 i--; 55 continue; 56 } 57 obj[cur]=cur; 58 } 59 obj=null; 60 }; 61 var ary=[]; 62 var ary1=[12,34,34,34,34,34,56,66,66,66,777]; 63 ary.myUnique(); 64 Array.prototype.myUnique(); 65 ary1.myUnique(); 66 console.log(ary1); 67 68 //数组排序之链式写法 69 console.log("===========数组排序之链式写法=========") 70 //原理: 71 //aryDemo为什么可以使用sort方法?因为sort是Array.prototype上公有的方法,而数组是 72 //aryDemo是Array这个类的一个实例,所以可以使用sort方法--->所以只有数组才能使用Arra 73 //y原型上定义的属性和方法。 74 //sort执行完成的放回置是一个排序后的“数组”,(其实就是为了实现执行后返回的还是一个数组的实例) 75 //reverse执行完成的返回值是一个数组,可以继续执行pop 76 //pop执行完成的返回值是被删除的那个元素,不是一个数组了。也就是说pop后面是不能在继续”.“了。 77 //要想弄清楚为什么这样写必须搞清楚对象的原型链 78 // 79 //一句话:要想实现链式写法必须返回的是一个类的实例。 80 var aryDemo=[12,34,23,4,3,343,45,34,34,34,656]; 81 aryDemo.sort(function (a,b) { 82 return a-b; 83 }).reverse().pop(); 84 console.log(aryDemo); 85 86 </script> 87 </body> 88 </html>
7.原型链模式扩展-this和原型扩展-练习题
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>课时16:原型链模式扩展-this和原型扩展-练习题</title> 6 <!--在数组的原型上有一个方法叫做slice,要求:自己实现一个myslice方法。 7 Array.prototype.mySlice=function(){ 8 <js code > 9 } 10 考虑的情况: 11 slice(n,m); 12 slice(n); 13 slice(); 14 n和m是负数,什么情况? 15 n<m是什么情况 16 n和m的值超过数组的长度是什么情况 17 n和m不是有效数字是什么情况 18 . 19 .. 20 ... 21 22 不能使用数组内置的方法:不能使用数据内置的方法,比如添加不能使用push, 23 而是用ary[ary]; 24 25 2.(面试题)实现一个需求: 26 (5).plus(10).reduce(2) 5+10-2 27 Number.prototype.plus=function(num){}; 28 Number.prototype.reduce=function(num){}; 29 30 --> 31 </head> 32 <body> 33 <script type="text/javascript"> 34 35 </script> 36 </body> 37 </html>
8.原型链模式扩展-批量设置公有属性
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>课时17:原型链模式扩展-批量设置公有属性</title> 6 </head> 7 <body> 8 <script type="text/javascript"> 9 console.log("批量设置原型上的公有属性!"); 10 11 12 13 //jQuery就是使用这种方式进行构架的 14 function Fn() { 15 this.x=10; 16 } 17 //1.起别名 18 var pro=Fn.prototype;//把原来类型指向的地址赋值给我们的pro,现在他们 19 //操作的是同一个内存空间 20 pro.getX=function () { 21 22 }; 23 //2.重构原型对象的方式-->自己重新开辟一个堆内存, 24 function Fn1() { 25 this.x=100; 26 } 27 Fn1.prototype={ 28 constructor:Fn1,//必须手动指定constructor否则就是Object了。这样做的目的就是为了保持一直。 29 a:function () { 30 console.log("我是重构的!"); 31 }, 32 b:function () { 33 34 }, 35 }; 36 var f=new Fn1; 37 //能执行a. 38 //1)只有浏览器天生给Fn.prototype开辟的堆内存里面才有constructor,而而我们自己开辟 39 //的这个堆内存没有这个属性,这样constructor指向不在是Fn而是Object了 40 //为了和原来的保持一直,需要手动的增加constructor的指向 41 //手动增加一个constructor:Fn1 42 f.a(); 43 console.log(f.constructor); 44 f.b(); 45 46 //2.用这种方式给内置类增加公有的属性 47 //给内置类Array增加数组去重的方法 48 Array.prototype.unique=function () { 49 //js code 50 }; 51 52 Array.prototype={ 53 constructor:Array, 54 unique:function () { 55 56 }, 57 }; 58 console.log("=====强行清空Array内置方法===========") 59 console.dir(Array.prototype); 60 //我们使用方式会把之前已经存在原型上的属性和方法替换掉,所以我们中这种方法 61 //修改内之类的话,浏览器是给屏蔽的。 62 //但是我们可以一个一个的修改浏览器的内置方法。如果方法名和原来的内置的重复了, 63 //会把人家内置的修改掉---->以后我们在内置内的原型上增加方法,命名都需要加上特殊的前缀。 64 console.log("===========另外一个例子==============="); 65 var ary=[1,2,3,4,5,6,7]; 66 ary.sort(); 67 console.log(ary); 68 69 Array.prototype.sort=function () { 70 // console.log(this)//this-->aryDemo 我们当前操作的对象, 71 console.log("ok!"); 72 } 73 // 修改数组中的内置方法,sort使他成为自己的内置方法。 74 var aryDemo=[1,2,2,1,2,2,3,4,5,6,7]; 75 aryDemo.sort(); 76 console.log(aryDemo); 77 </script> 78 </body> 79 </html>
9.深入扩展原型链模式常用的六种继承方式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>18.深入扩展原型链模式常用的六种继承方式</title> 6 </head> 7 <body> 8 9 <script type="text/javascript"> 10 //--->div ,a,document,window, 11 12 function Fn() { 13 this.x=100;//这里的this指的是Fn的一个实例 14 //->在类的函数体中写的this.xxx=xxx都是当前类的实例 15 this.getX=function () { 16 console.log(this.x); 17 } 18 } 19 Fn.prototype.getX=function () { 20 console.log(this.x); 21 }; 22 Fn.prototype.setX=function (n) { 23 this.x=n; 24 }; 25 //在类的原型上写的都是给当前类的实例或者当前类 26 //见图片原型链图片.PNG 27 var f1=new Fn; 28 console.log(f1.hasOwnProperty("x")); 29 //1.所有的函数数据类型都天生自带一个属性:prototype,它存储的值是一个对象数据类型的值,浏览器默认为其开辟一个对 30 //一个堆内存 31 //2.在浏览器默认给prototype默认开辟的这个堆内存上都有一个默认的属性: 32 //constructor,指向当前类本身 33 //3.每一个对象数据类型(普通函数,数组,正则,实例,prototype)都天生自带一个属性(__proto__):__prototype__,指向当前实例所属类的原型。 34 var f1=new Fn; 35 var f2=new Fn; 36 37 38 //1.看方法执行的时候,”.“前面是谁,this就是谁。 39 //2.吧函数中this替换成分析的结果 40 //3.按照原型链的查找模式找到对应的值即可 41 f1.getX();//100;f1.getX();,console.log(f1.x); 42 // 练习 43 f2.getX();//100; 44 f2.__proto__.getX();//this-->f2.__prototype__,结果是undefined 45 46 Fn.prototype.setX(300);//X设置成300; 47 f2.getX();//100; 48 f2.__proto__.getX();//300 49 50 </script> 51 </body> 52 </html>
10.一道题(原型链)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <script type="text/javascript"> 9 function Fn(num) { 10 this.x=this.y=num; 11 } 12 Fn.prototype={ 13 x:20, 14 sum:function () { 15 console.log(this.x+this.y); 16 } 17 }; 18 var f=new Fn(10); 19 console.log(f.sum==Fn.prototype.sum);//true; 20 f.sum();////f.x=10 f.y=10 结果为20 21 Fn.prototype.sum();//this.x=20; 结果是: NaN; 22 console.log(f.constructor);//Object 23 24 //这道题可以的。 25 </script> 26 27 </body> 28 </html>
11.原型链复习
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>原型链综合复习参考2</title> 6 </head> 7 <body> 8 <script type="text/javascript"> 9 function Fn() { 10 this.x=100; 11 } 12 Fn.prototype={ 13 //注意构建 constructtor. 14 //浏览器不会开constructtor,但是我可以自己加啊。 15 constructor:Fn, 16 a:function () { 17 18 }, 19 b:function () { 20 21 }, 22 23 }; 24 var f=new Fn; 25 //这种方式如果之前原型上存在一些方法,我们现在新创建的对象会把之前写的那些覆盖掉。 26 //但是所有内置类的原型都有保护; 27 //比如: 28 Array.prototype={}; 29 //所以浏览器禁止创建一个新对象来扩展原型上的方法, 30 //自己创建的对象不会天生自带constructor,所以导致了我们的f.constructor的结果 31 //是Object而不是我们认为的Fn了。 32 33 </script> 34 </body> 35 </html>
12.在内之类的原型上扩展方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>在内之类的原型上扩展方法</title> 6 </head> 7 <body> 8 9 10 <script type="text/javascript"> 11 var ary=[11,22,33,44]; 12 ary.pop();//this-->ary 13 ary.__proto__.pop();//this--->ary.__proto__-->Array.prototype 14 //这种方式不可以删除。 15 16 //基于内置类的原型扩展方法,我们需要注意的事项:我们自己编写的方法名最好加上特殊的前缀,防止把内置方法覆盖掉 17 Array.prototype.myPaixu=function myPaixu () { 18 //this-->ary; 19 var obj={}; 20 for (var i =0;i<this.length;i++){ 21 var cur=this[i]; 22 if(obj[cur]==cur){ 23 this[i]=this[this.length-1]; 24 this.length--; 25 i--; 26 continue; 27 28 } 29 obj[cur]=cur; 30 } 31 obj=null; 32 //实现链式写法。 33 return this; 34 }; 35 var ary1=[1,2,2,3,3,5,66,66,66]; 36 ary1.myPaixu().sort(function (a,b) { 37 return a-b; 38 }); 39 console.log(ary1); 40 </script> 41 </body> 42 </html>
13.深入扩展原型链模式常用的六种继承方式(1)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>19深入扩展原型链模式常用的六种继承方式</title> 6 </head> 7 <body> 8 <script type="text/javascript"> 9 10 var obj={}; 11 var obj=new Object(); 12 //这2中方式没有区别,一个是字面量,一个是通过构造函数方式。 13 14 //扩展Object属性 15 Object.prototype.aaa=function AAA() { 16 console.log("我是自定义的公有属性!") 17 }; 18 19 var obj2={name:"lizbeo",age:23}; 20 for (var shuXing in obj2){ 21 //---->for in 循环在遍历的时候可以把自己私有的和在它 22 //所属类的原型上扩展的属性和方法都可以遍历到 23 //但是一般情况下,我们遍历一个对象只需要遍历私有的即可, 24 //我们可以使用以下的判断 25 if(obj2.propertyIsEnumerable(shuXing)){} 26 console.log(shuXing); 27 // if(obj2.hasOwnProperty(shuXing)){ 28 // console.log(shuXing) 29 // } 30 } 31 </script> 32 </body> 33 </html>
14.深入扩展原型链模式常用的六种继承方式(2)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>19深入扩展原型链模式常用的六种继承方式2</title> 6 </head> 7 <body> 8 9 10 <script type="text/javascript"> 11 // 1. 原生继承!!!!!!!!! 12 //--->#div.__pro__-->HTMLDivElement.prototype-->HTMLElement.prototype 13 //-->Element.prototype-->Node.prototype--->EventTarget.prototype--->O 14 //bject.prototype; 15 function myObject() { 16 this.getInformation=function () { 17 console.log("我是myObject的私有属性!"); 18 } 19 20 } 21 myObject.prototype=new Object; 22 myObject.prototype.aaaaaa=function () { 23 console.log("我是继承原生继承!"); 24 }; 25 26 function myTargetElement () { 27 28 } 29 myTargetElement.prototype=new myObject; 30 31 var A=new myTargetElement(); 32 A.aaaaaa(); 33 A.getInformation(); 34 //这就是原生继承。 35 //====》原生继承是我们JS中最常用的继承方式, 36 //-----》1)子类B想要继承父类A中的属性和方法(私有+公有),只需要让B的prototype=new A的一个实例;即可 37 //注意以下,所有方法,包括私有方法很关键。 38 //2)原型继承有个特点:他是把父类中私有的+公有的都继承到了子类的原型上(子类公有) 39 40 </script> 41 </body> 42 </html>
15.深入扩展原型链模式常用的六种继承方式(3)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>19深入扩展原型链模式常用的六种继承方式3</title> 6 </head> 7 <body> 8 9 <div id="div1"></div> 10 <script type="text/javascript"> 11 var doc=document.getElementById("div1"); 12 // 原型链的核心:见图 原型链的核心思想.PNG 13 //原生继承并不是把父类中的属性和方法克隆一份一摸一样的给B,而是让B和A之间增加了原型链的连接,以后B的实例想要从A中 14 //获得getX的方法,需要一级一级的去查找。 15 //但是有一个弊端: 16 //见图 原型链的核心思想2.PNG 17 18 //--->核心:原型继承并不是把父类中的属性和方法克隆一个一摸一样的给B,而是让B和A之间增加了原型链的连接,以后B的实例想要从 19 //A中的getX方法,需要一级级向上查找来使用。 20 21 22 23 </script> 24 </body> 25 </html>
16.深入扩展原型链模式常用的六种继承方式(4)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>19深入扩展原型链模式常用的六种继承方式之其他继承</title> 6 </head> 7 <body> 8 9 <script type="text/javascript"> 10 // function A() { 11 // this.x=100; 12 // } 13 // A.prototype.getX=function () { 14 // console.log(this.x); 15 // }; 16 // function B() { 17 // 18 // A.call(this); 19 // } 20 // var n=new B; 21 // console.log(n.x); 22 // //call继承:就是把父类私有的属性和方法 克隆一根一摸一样的作为子类私有的属性 23 // 还有一些继承 :1.冒充对象继承:把父类私有的+公有的克隆一份一摸一样的给子类。 24 </script> 25 </body> 26 </html>
--lzb