【JavaScript】面向对象、原型和原型链、继承

摘要

面向对象三大特点:
封装:将事物的属性和功能集中定义在一个对象中
继承:父对象的成员,子对象不用反复创建,也可直接使用
多态:同一类事物或父子关系的事物,也可能表现出不同的状态

【JavaScript】面向对象、原型和原型链、继承

1. *****面向对象: OOP
什么是对象: 内存中集中存储多个数据或函数的存储空间,再起一个名字。
对象是程序中描述现实中一个具体事物的属性和功能的结构
什么是面向对象: 程序中都是先用对象描述现实中一个具体事物,然后再访问对象的属性和功能。
为什么面向对象: 现实中,一个属性或一个功能都必须依附在一个具体的事物上才有意义!不同的事物,即使是同一功能,它的定义也可能不一样。

如何使用面向对象:
1. 先创建对象: ——封装
描述现实中一个事物,需要两类成员:
1.事物的属性,会成为程序中对象的属性
属性: 对象中存储一个数据的变量
2.事物的功能,会成为程序中对象的方法
方法: 保存在对象中的一个函数
属性和方法统称为: 对象的成员
将一个事物的属性和方法集中定义在一个对象中。
3种:
1. 直接量,创建*一个*独特的对象:
var obj={
属性名:属性值,
...:...,
方法名:function(...){...},
...:...
}
*****js中一切都是对象!对象的底层都是关联数组!
1. 每个成员名其实都是字符串,但对象中成员名的引号可省略
2. 都可用for in遍历对象的每个成员
3. 对象也可在任何时候添加新成员
对象自己的方法,如何使用自己的属性:
*****this: 在函数调用时,引用正在调用函数的对象 的变量
其实就是.前的对象
不使用任何对象调用的函数,this默认是window

2.用new关键字: var obj=new Object();//创建一个空对象
obj.属性名=值;
obj.方法名=function(){...}

*****3.使用构造函数,反复创建*多个*相同结构的对象:
构造函数: 专门描述一类对象的结构的函数
为什么: 代码重用!
如何使用: 2步:
1. 定义构造函数/类型:
function 类型名/构造函数名(属性参数,...){
为当前对象添加指定属性,赋值为属性参数的值:
比如: this.属性名=属性参数
this.方法名=functon(...){...}
}
2. 调用构造函数创建对象,也称为创建类型的一个实例
——也称为实例化!
var obj=new 构造函数名/类型名(属性值列表,...);
new执行了4个操作:
1. 创建一个空对象
2. ?
3. 用新对象调用构造函数
4. 返回新对象的地址给变量

2. 访问对象成员:
1. 访问属性: 对象.属性名 -> 和变量完全一样
2. 调用方法: 对象.方法名() -> 和函数完全一样

 

做一个lilei、hanmeimei的自我介绍
//创建一个对象,描述lilei
			//属性: sname : "LiLei"  sage : 13
			//功能: intrSelf: 
			//				输出"I'm Li Lei,I'm 13"
			var lilei={
				sname:"LiLei",
				sage:13,
				intrSelf:intrSelf
			}
			function intrSelf(){
					dialog.innerHTML=
						"I'm "+this.sname+",I'm "+this.sage;
						  //当前对象的sname    //当前对象的sage
					dialog.style.display="block";
			}
			//创建一个对象,描述hmm
			//属性: sname:"Han Meimei"  sage:14
			//功能: intrSelf:同lilei
			var hmm={
				sname:"Han Meimei",
				sage:14,
				intrSelf:intrSelf
			}

换种思路

function Student(sname,sage){
				this.sname=sname;
				this.sage=sage;
			}
			//为Student的prototype(原型)对象中添加intrSelf方法
			Student.prototype.intrSelf=function(){
					dialog.innerHTML=
						"I'm "+this.sname+",I'm "+this.sage
						+"I'm from "+this.className;
						  //当前对象的sname    //当前对象的sage
					dialog.style.display="block";
			}
			//为所有学生添加共有属性班级名为初一2班
			Student.prototype.className="初一2班";
			var lilei=new Student("Li Lei",13);//实例化
			var hmm=new Student("Han Meimei",14);//实例化

1. *****面向对象:
面向对象三大特点:
封装:将事物的属性和功能集中定义在一个对象中
继承:父对象的成员,子对象不用反复创建,也可直接使用
多态:同一类事物或父子关系的事物,也可能表现出不同的状态

js中都是继承原型:
原型对象: 集中保存一类对象共有成员的父级对象
何时使用原型对象: 凡是所有子对象共有的属性*值*和方法,都要在原型中集中定义一次。子对象共同使用。
如何使用:
如何获得原型对象: 每个函数都有一个prototype属性引用自己的原型对象。
回顾: new 4件事:
1. 创建空对象
2. 设置空对象的__proto__属性继承构造函数的原型对象
原型对象中的属性,新对象可直接使用,不用重复定义
3. 调用构造函数为新对象添加属性和方法
4. 返回新对象地址保存在变量中
如何向原型对象中添加共有属性和方法:
构造函数.prototype.属性名/方法名=....

原型链: 由各级对象的__proto__属性连续继承形成的链式结构
用来控制属性的使用顺序: 自己有,就不用父级的。
自己没有,才到父级找。
如果父级没有,继续延原型链向上找
如果到顶级对象都没有,才返回undefined
vs 作用域链: 用于控制变量的使用顺序。

自有属性和共有属性:
1. 判断自有属性: var bool=obj.hasOwnProperty("属性名");
如果指定"属性",直接保存在obj本地,则是自有属性,返回true。
如果指定"属性",没有保存在obj本地,则返回false。
2. 判断共有属性: 不是自有,且在原型链中有
!obj.hasOwnProperty("属性名")
&&("属性名" in obj)//判断obj的原型链上是否包含指定属性。

内置对象的原型对象: 保存了内置对象共有的API和属性值

原型相关API:
1. 获得对象的父级原型对象: 2种:
1. 通过构造函数获得: 构造函数.prototype
2. 通过子对象获得:
obj.__proto__ 问题: __proto__是内部属性,可能被禁用
Object.getPrototypeOf(obj)
2. 判断两对象间的父子关系:
父对象.isPrototypeOf(子对象)
如果父对象确实是子对象的父级,就返回true
如果父对象不是子对象的父级,就返回false
强调: 检查整个原型链

重写(override): 如果子对象觉得父对象的成员你不好用,可在本地定义同名成员覆盖父对象成员

以上面的为例,
看一下自有共有属性!
//遍历hmm的每个属性和功能
			for(var key in hmm){
				console.log(key+":"+hmm[key]);//不能用hmm.key
			}
			//检查lilei对象的自有,共有属性
			function checkProp(obj,prop){
				console.log(prop+":"+(
					obj.hasOwnProperty(prop)?"自有":
	/*(!obj.hasOwnProperty(prop))&&*/(prop in obj)?"共有":
					"没有"
				));
			}
			checkProp(lilei,"sage");//自有
			checkProp(lilei,"className");//共有
			checkProp(lilei,"sort");//没有
			checkProp(hmm,"className");//共有
李东辉

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

目前评论:2   其中:访客  2   博主  0

  1. avatar 生晓's blog 4

    博主买犀牛书了吗