JavaScript提高篇之面向对象之单利模式工厂模型构造函数原型链模式
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript提高篇之面向对象之单利模式工厂模型构造函数原型链模式相关的知识,希望对你有一定的参考价值。
1.单例模式
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.工厂模式
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.构造函数模式基础
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.构造函数模式扩展
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原型链模式基础
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和原型扩展
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和原型扩展-练习题
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.原型链模式扩展-批量设置公有属性
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.深入扩展原型链模式常用的六种继承方式
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.一道题(原型链)
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.原型链复习
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.在内之类的原型上扩展方法
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)
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)
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)
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)
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