面向对象

一.定义属性

			//对象Object中的属性(property)有4个Attribute:
			//分别为[Configurable]:能否通过delete删除该property
			//[Enumerable]:能否通过for-in遍历该property
			//[Writable]:能否修改property的值
			//[Value]:默认为undefinded.当age="11"时,[Value]即为11
			//通过Object.defineProperty()修改默认property的4种attribute
			var myPerson={};
			//调用该方法时,若不指定,默认都是false
			Object.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为false
			console.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);//true
			console.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));//true
			console.log(Object.getPrototypeOf(teacher1)==Teacher.prototype);//true
			
			//读取对象的某个属性的流程:实例对象(person1有sayName属性吗)->原型对象(person1的原型有sayName属性吗)
			
			//teacher1对应的原型为Teacher
			console.log(Object.getPrototypeOf(teacher1));
			//实例可以覆盖原型中的属性.让原型中的属性失效.(但是不会修改原型中的属性值)
			teacher1.name="newNickccc";
			console.log(teacher1.name);//newNickccc
			
			//delete 可以删除对象实例中的属性,却不能删除原型中属性
			delete teacher1.name;
			console.log(teacher1.name);//nick
			
			//hasOwnProperty检测一个属性来自实例还是来自prototype
			console.log(teacher1.hasOwnProperty("name"));//
			
			//in,只要一个属性可以访问,无论是实例还是来自prototype均返回true
			console.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);//false
			console.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);//true
			console.log(instance instanceof SuperType);//true
			console.log(instance instanceof Object);//true
			console.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);
			}
			//子类对象1
			var s1=new SubClass("nick",22);
			s1.colors.push("black");
			//[red","blue","green","black"]
			console.log(s1.colors);//由于调用构造器,属性均为每个实例私有的.互不影响
			//方法定义在了原型链中,为所有实例共享,相当于java中的只有一份方法
			s1.sayName();
			s1.sayAge();
			//子类对象2
			var 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){
				//创建临时性的构造函数F
				function 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"
				}
			});




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FlyingZCC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值