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");//共有