JavaScript-形象理解面向对象、原型和继承

来源:互联网 发布:网络侮辱他人 寻衅滋事 编辑:程序博客网 时间:2024/05/16 18:29

       这是第二次整体复习JavaScript的面向对象与原型方面的知识。这部分的知识比较抽象但是又十分重要。它对后期类库的封装,整体架构的实现非常重要。在这节我将对每个方式进行形象全面的讲解。

       本节要点

//JS面向对象和原型//1.创建类:a.利用new Object()创建。b.使用字面量创建(直接实例化对象,不需要new运算符)c.利用构造函数创建//2.实例化属性和原型属性的区别.实例对象和类的关系//3.原型链的理解,prototype和__proto__的区别//4.继承模式:a.工厂模式.b.原型链模式.c.组合模式.d.原型模式.e.原型组合模式.f.构造寄生</span>

    1.JavaScript创建类

     利用object()创建

//1.利用Objectvar obj = new Object();obj.a = "A";obj.b = "B";obj.func = function(){console.log(this.a + this.b);//这里可以用this};//cosole.log(this.a);//这里的this是window下的//obj.func();</span>

     使用工厂模式

//集中实例化对象,工厂模式var createObj = function(a,b){var obj = new Object();obj.a = a;obj.b = b;obj.func =function(){return this.a + this.b;};return obj;}var obj1 = createObj("a1","b1");var obj2 = createObj("a2","b2");console.log(obj1.func());console.log(obj2.func());console.log(obj1 instanceof Object);//无法判断obj1的具体类型</span>

    使用构造函数

//2.利用构造函数//利用构造函数能集中实例化,但是没有new Object(),但它内部自动进行new Object();//this直接表示这个对象//不需要返回对象,后天会直接返回//delete方法可以删除实例属性和方法及原型属性和方法//hasOwnProperty()判断方法或属性是否在构造函数中。而in则表示既在原型也在实例中//instanceof 和 isPrototypeOf分别表示是否为一个对象的实例和是否为一个函数的原型。//使用构造函数时,首字母要大写//必须使用new运算符/*function Obj(a,b){    this.a = a;    this.b = b;    this.func = function(){        return this.a + this.b;    };}*///var obj = new Obj("a1","b1");//console.log(obj.func());//console.log(obj instanceof Obj);        //可以判断具体的类//var o = new Object();//call方法的理解:相当于把Obj方法放在对象o中//即改变Obj的上下文对象为o//Obj.call(o,"a2","b2");//console.log(o);//理解构造函数内部函数的关系//var objTest = new Obj("a1","b1");//console.log(obj.func() == objTest.func());    //计算过后的值相等//console.log(obj.func == objTest.func);        //函数的引用地址是不同的,是两个不同的实例化对象//使用原型。原型prototype是函数的一个自带属性。可以看作是构造函数在实例化时创作的那个对象。//使用原型的好处:可以共享变量和方法//function Aaa(){}//var aaa = new Aaa();//Aaa.prototype.b = "b";        //必须要var aaa = new Aaa()过后才能访问到这个b//aaa.__proto__.b = "b1";        //共享属性//console.log(aaa.b);            //b1//Aaa.b = "b1";                //相当于静态属性,必须通过Aaa.b才能访问到,aaa.b是访问不到的//console.log(Aaa.b);//Aaa.prototype.func = function(){            //原型方法的地址是相同的,实例方法每次实例化时都要开辟新的空间//    console.log(this);            //这个this代表构造函数实例化的原型//}//__proto__和prototype的区别//__proto__是原型的指针,而prototype是函数的一个属性//var aaa = new Aaa();//console.log(aaa.__proto__ == Aaa.prototype);    //true。//constuctor是原型的一个属性,可以得到构造函数//console.log(Aaa.prototype.constructor == aaa.__proto__.constructor);    //true</span>

   2.原型

    构造函数创建原型和字面量创建原型的区别

//1.构造函数创建:function Person(){};Person.prototype.name = "Wu";Person.prototype.age = 12;console.log(Person.prototype.constructor);        // Person()//2.字面量创建function Person(){};Person.prototype ={    //constructor : Person,                        //将constructor指针指向Person    name : "wu",    age : 12};console.log(Person.prototype.constructor);        // Object()</span>

     原型的缺点

function Family(){};Family.prototype = {size : 3,member : ["mother","father"],show : function(){return this.size;}};//首先查看原型的数据共享问题var family1 = new Family();console.log(family1);family1.size = 4;//虽然Family.prototype中有size属性,但这里实际上是在family1对象中创建了一个size属性。console.log(family1.show());//这里由于family1中有实例属性size,根据就近原则,所以输出是4//family1.member = ["mother","father","me"];//这里实际上也是创建了一个实例属性family1.member.push("me");//而这个则是对引用属性即原型属性的值进行了修改,而原型属性具有共享的功能var family2 = new Family();console.log(family2.show());//这里的family2中没有size的实例属性,只有原型属性console.log(family2.member);//数组是修改后的</span>

      使用构造函数+原型链的模式

//使用构造函数+原型的组合模式,可以解决构造函数传参和数据私有化的问题,但是感觉封装性不好function Family(member){this.member= member;};Family.prototype = {constructor : Family,size : 3,show : function(){return this.size;}};//使用动态原型模式function Family(member){this.member = member;if(typeof this.show != "function"){//避免重复实例化,这里的方法不能带括号,不然会出错console.log("****");//Family.prototype = {//不能用字面量的方式//constructor : Family,//size : 3,//show : function(){//return this.size;//}//};Family.prototype.show = function(){return this.member;};}};var family1 = new Family(["father","mother"]);console.log(family1);console.log(family1.show());var family2 = new Family(["father","mother","me"]);console.log(family2.show());</span>

      使用寄生构造函数

//使用寄生构造函数。即构造函数 + 工厂模式//每次实例化构造函数都创建了一个新的Obj,保持的对象属性的私有化function Family(member){var obj = new Object();obj.member = member;obj.show = function(){return this.member;};return obj;}var family1 = new Family(["father","mother"]);family1.member.push("sister");var family2 = new Family(["father","mother","me"]);console.log(family1.show());console.log(family2.show());</span>

     3.继承

      基本继承

//基本继承function Man(){};//子类型function Person(){//超类型this.age = 2;};Man.prototype = new Person();//利用原型链实现继承var man = new Man();console.log(man.age);</span>

    对象冒充继承

//使用对象冒充实现继承function Person(age){//一般来说,需要共享的数据放在原型中,需要私有化的数据放在构造函数中this.age = age;};Person.prototype.func = function(){return this.age;//使用对象冒充无法访问到这个方法};var person = new Person(3);function Man(age){Person.call(this,age);//使用call函数。call函数相当如将Person方法作为Person的实例方法。即改变Person的上下文对象为Man};//但是使用对象冒充的方式只能继承实例属性和方法,无法继承原型中的属性和方法var man = new Man(3);console.log(man.age);</span>

     使用对象冒充 + 原型链的方式

//使用对象冒充 + 原型链的方式解决对象冒充无法继承原型数据和方法的问题//其中对象冒充可以继承实例方法和属性,原型链可以继承原型方法和属性function Person(age){this.age = age;};Person.prototype.func = function(){return this.age;};function Man(age){Person.call(this,age);};Man.prototype = new Person();//增加了原型链var person = new Person(3);var man = new Man(3);console.log(man.func());//使用原型继承function obj(o){function F(){};F.prototype = o;return new F();};var person = {age : 2,member : ["father"]};var man = obj(person);man.member.push("mother");//这里改变的是引用类型的值,即改变的是person中的member,能实现数据的共享var woman = obj(person);console.log(woman.member);</span>

     原型组合模式

//在使用原型链和构造组合模式时出现了:对象冒充时需要Person.call(this);然后在原型链时Man.prototype = new Person();//出现了两次调用超类型的情况。为了解决这种情况,可以利用一个中转函数把超类型中的原型属性复制到子类型中,实例属性和方法则通过对象冒充来继承function obj(o){//中转函数function F(){};F.prototype = o;return new F();};function create(father,son){//工厂模式var f = obj(father.prototype);f.constructor = son;//constructor是原型的一个属性,在复制原型属性和子类型之后,应该还是修改它的constructor指向son.prototype = f;};function Person(age){//超类型this.age = age;};Person.prototype.show = function(){return this.age;};function Man(age){//子类型Person.call(this,age);};create(Person,Man);var man = new Man(4);console.log(man.show());</span>


5 0
原创粉丝点击