面向对象

来源:互联网 发布:艾滋病现状最新数据 编辑:程序博客网 时间:2024/06/01 21:33
一.定义属性

//对象Object中的属性(property)有4个Attribute://分别为[Configurable]:能否通过delete删除该property//[Enumerable]:能否通过for-in遍历该property//[Writable]:能否修改property的值//[Value]:默认为undefinded.当age="11"时,[Value]即为11//通过Object.defineProperty()修改默认property的4种attributevar myPerson={};//调用该方法时,若不指定,默认都是falseObject.defineProperty(myPerson,"age",{configurable:false,enumerable:false,writable:false,value:"zxx"});console.log(myPerson.age);//删除age属性.当指定configurable为false时.删除无效.delete myPerson.age;console.log(myPerson.age);//当指定enumerable为false时不可迭代for(prop in myPerson){console.log(prop+":"+myPerson[prop]);}myPerson.age="1122";//当指定writable为false时,不可修改console.log(myPerson.age);

二.创建对象

//(1)var person=new Object();person.name="zc";person.age=1;person.sayHello=function(){console.log(person.name);}//(2)字面量方式var people={name:"zx",age:11,sayHello:function(){console.log(this.name);}};//(3)var man={};Object.defineProperty(man,"name",{writable:false,value:"zx"});console.log(man.name);man.name=1;//修改无效,因为writable为falseconsole.log(man.name);console.log("--getter,setter--");//定义多个属性        //(4)工厂模式.缺点,无法得知获取的对象的具体类型function createPerson(name,age,job){var o=new Object();o.name=name;o.age=age;o.sayName=function(){console.log(this.name);}return o;//返回Person对象}var person1=createPerson("zx",11,"jj");//(5)构造函数模式,构造器.缺点每次new创建的都是新的对象//任何函数,只要通过new操作符来调用,都可以作为构造函数//所谓"构造函数",其实就是一个普通函数,但是内部使用了this变量。//对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。//缺点:每个方法都要在 每个实例上重新创建一遍function Person(name,age,job){this.name=name;this.age=age;//其实相当于this.sayName=new Function(){console.log(this.name);}this.sayName=function(){console.log(this.name);}}var person2=new Person("zx",11,"sf");console.log(person2.constructor==Person);//trueconsole.log(person2 instanceof Person);
//(6)创建原型对象//每个函数都有一个prototype属性,该属性是一个指针,指向一个对象,//该对象的用途是包含可以由特定类型的  所有实例共享的属性和方法//原型可以让所有实例对象共享   该原型   包含的属性和方法//缺点:对于基本数据类型的原型属性,可以通过在对象中添加同名属性来屏蔽//但是对于 引用类型的 原型属性,问题突出function Teacher(){//prototype属性指向函数的 原型对象//定义原型属性的第一种方式Teacher.prototype.name="ZXX";};//如果此时先创建一个对象,再完全重写原型var oldTeacher=new Teacher();//定义原型属性的第二种方式//这种方式定义原型,相当于重写了prototype函数.//此时Teacher.prototype.constructor不再指向Teacher函数,而是指向Object构造函数Teacher.prototype={//可以直接指定constructor属性,但这样导致constructor变得可以枚举//constructor:Teacher,name:"nick",age:25,job:"he",sayName:function(){console.log(this.name);}};//使用这种方式,重设原型中的constructor属性,可以设置为不可枚举Object.defineProperty(Teacher.prototype,"constructor",{enumerable:false,value:Teacher});//由于重写原型对象(相当于new了)  发生 在 创建该对象之后,//该对象中隐含的[[prototype]]属性指向的还是之前的原型对象,所以报错,找不到该方法//若不完全重写原型对象,而是只向原型对象中添加某个方法,不会发生这种情况//oldTeacher.sayName();//所有原型对象都拥有一个constructor属性console.log(Teacher.prototype.constructor);var teacher1=new Teacher();console.log(Teacher.prototype.isPrototypeOf(teacher1));//trueconsole.log(Object.getPrototypeOf(teacher1)==Teacher.prototype);//true//读取对象的某个属性的流程:实例对象(person1有sayName属性吗)->原型对象(person1的原型有sayName属性吗)//teacher1对应的原型为Teacherconsole.log(Object.getPrototypeOf(teacher1));//实例可以覆盖原型中的属性.让原型中的属性失效.(但是不会修改原型中的属性值)teacher1.name="newNickccc";console.log(teacher1.name);//newNickccc//delete 可以删除对象实例中的属性,却不能删除原型中属性delete teacher1.name;console.log(teacher1.name);//nick//hasOwnProperty检测一个属性来自实例还是来自prototypeconsole.log(teacher1.hasOwnProperty("name"));////in,只要一个属性可以访问,无论是实例还是来自prototype均返回trueconsole.log("name" in teacher1);//true//同时使用hasOwnProperty()和in操作符,可以确定该属性到底存在于对象还是原型中function myHasPrototypeProperty(obj,name){return !obj.hasOwnProperty(name)&&(name in obj);}//keys:返回实例中所有 可枚举 的属性的字符串数组console.log(Object.keys(teacher1));//无论实例属性是否可以枚举,都可以获取,传入的是对象console.log(Object.getOwnPropertyNames(teacher1));//原生引用类型(Object,Array,String等)都是在其构造函数的原型上定义了方法.console.log(typeof Array.prototype.sort);//function//若Array.prototype中有sort()方法//可修改,或添加方法String.prototype.zc=function(){console.log("这是自定义zcString中的方法");}var strz="zc";strz.zc();

                //(7)构造函数模式 与 原型模式结合//构造函数定义每个实例私有的属性function Student(name,age){this.name=name;this.age=age;this.frineds=["a","b"];}//定义实例共有的属性Student.prototype={constructor:Student,sayName:function(){console.log(this.name);}}var stu1=new Student("zxx",23);var stu2=new Student("zax",24);stu1.frineds.push("c");console.log(stu1.frineds);console.log(stu2.frineds);console.log(stu1.frineds==stu2.frineds);//falseconsole.log(stu1.sayName==stu2.sayName);//true


三.继承

        //(1)原型链//缺点:仅仅使用原型继承,依然是会导致引用类型属性 共享 的 问题function SuperType(){this.name="super类型";age=111;}SuperType.prototype.getSuperValue=function(){return this.name;}function SubType(){this.subName="sub类型";}//继承SuperType.!!!!继承实现的本质是 重写原型对象 为 SuperType的实例对象//即 原来存在于SuperType的实例中的所有属性和方法,现在也存在于SubType.prototype中了//此时若调用子类型中的某个方法,会按照subType->superType(此时即为suType的原型)->superType.prototype->Object->Object.prototype寻找//不能使用字面量方式实现继承,因为这样相当于重写了prototype函数SubType.prototype=new SuperType();//在确立了继承关系后,定义子类型自己的getSubValue方法。这样就在继承了SuperType的属性和方法的基础上又添加了一个新方法SubType.prototype.getSubValue=function(){return this.subName;}//重写父类中的getSuperValue方法.子类的prototype指向的是父类的实例SubType.prototype.getSuperValue=function(){return "zx子类重写后的方法";}//子类型调用重写后的方法var sub=new SubType();console.log(sub.getSuperValue());//zx子类重写后的方法//父类型调用重写后的方法var super2=new SuperType();console.log(super2.getSuperValue());//输出仍然 是 super中的方法//创建子类型var instance=new SubType();console.log(instance.getSuperValue());console.log(instance.getSubValue());console.log(instance instanceof SubType);//trueconsole.log(instance instanceof SuperType);//trueconsole.log(instance instanceof Object);//trueconsole.log(instance.name);       //继承(2)借用构造器 call(),优点是可以向父类构造方法传参        //实现:在子类型构造函数内部调用超类构造函数.function Sup(name){this.name=name;this.colors=["red","blue","green"];}function Sub(){//优点:可在子类型创建时向父类型的构造方法中传递参数//问题:方法都定义在构造函数中,无法复用.//且在超类中定义的方法,对子类型不可见(因为只在子类型的构造函数中调用了父类型的构造函数,其他地方,子类型没有父类型的指针).Sup.call(this,"xiaoz");}var instance1=new Sub();instance1.colors.push("black");//子类型可以直接调用父类中的属性console.log(instance1.colors);var instance2=new Sub();console.log(instance2.colors+instance2.name);                //!!!继承(3)组合继承  即 原型链+借用构造函数console.log("--组合继承--");//使用原型链实现对原型 属性 和 方法 的 继承.借用构造函数 实现 对 实例属性的继承function SuperClass(name){this.name=name;this.colors=["red","blue","green"];}SuperClass.prototype.sayName=function(){console.log(this.name);}//子类function SubClass(name,age){SuperClass.call(this,name);//继承父类中的属性this.age=age;}//继承方法SubClass.prototype=new SuperClass();//定义子类方法SubClass.prototype.sayAge=function(){console.log(this.age);}//子类对象1var s1=new SubClass("nick",22);s1.colors.push("black");//[red","blue","green","black"]console.log(s1.colors);//由于调用构造器,属性均为每个实例私有的.互不影响//方法定义在了原型链中,为所有实例共享,相当于java中的只有一份方法s1.sayName();s1.sayAge();//子类对象2var s2=new SubClass("nzdd",44);//[red","blue","green"]console.log(s2.colors);s2.sayName();s2.sayAge();console.log(s1 instanceof SubClass);console.log(s1 instanceof SuperClass);console.log(s1 instanceof Object);console.log(s2 instanceof SubClass);console.log(s2 instanceof SuperClass);console.log(s2 instanceof Object);         //继承(4) 原型式继承function createObject(o){//创建临时性的构造函数Ffunction F(){}//将传入的参数o作为该构造函数的原型F.prototype=o;//返回这个临时类型作为一个新的实例return new F();}var person4={name:"zxxx",friends:["selly","tom","kitty"]};//返回的anotherPerson对象以person4对象为原型.//所以anotherPerson的prototype中包含  person4中的属性var anotherPerson=createObject(person4);anotherPerson.name="Greg";anotherPerson.friends.push("Rob");var yetPerson=createObject(person4);yetPerson.name="Linda";yetPerson.friends.push("Brr");//为何string类型值没变,Array类型值改变了??!!//!!!!原型中所有引用类型的变量为所有实例共享,基本类型则为私有console.log(person4.name);//"zxxx"console.log(person4.friends);//["selly", "tom", "kitty", "Rob", "Brr"]//ECMAScript5通过新增Object.create(作为新对象原型的对象,作为新对象额外属性的对象-可选)   规范化了原型式继承var person41={name:"zxxx",friends:["selly","tom","kitty"]};//[1]传入一个参数var anotherPerson1=Object.create(person41);anotherPerson1.name="Greg";anotherPerson1.friends.push("Rob");var yetPerson1=Object.create(person41);yetPerson1.name="Linda";yetPerson1.friends.push("Brr");console.log(person41.name);//"zxxx"console.log(person41.friends);//["selly", "tom", "kitty", "Rob", "Brr"]//[2]传入两个参数var anotherPerson2=Object.create(person41,{name:{value:"Grrrrr"}});




原创粉丝点击