JavaScript-day20-个人学习笔记
一、面向对象:在程序中都是用一个对象来描述现实中一个具体的东西。
现实中的一个东西都包含属性和功能:属性:描述一个东西特点的变量;功能:东西可以执行的操作。
现实中东西的属性会成为对象中的属性变量;现实中东西的功能会成为对象中的方法(函数)。
1、什么是对象:封装多个数据的存储空间
2、什么是自定义对象:封装现实中一个东西的属性和功能的存储空间
3、面向对象三大特点:封装 继承 多态
(1)封装:将描述同一个东西的属性和方法定义在一个对象中
(2)继承:父对象中的属性和方法,子对象可直接使用
(3)多态:同一个对象,在不同情况下,呈现不同的状态。a、重载:同一个方法名,传入参数不同,执行不同的操作;b、重写:子对象觉得父对象的成员不好用,可自己定义一个,覆盖父对象的成员。
二、创建自定义对象:4种方式:
1、直接量:
var obj={'属性名1':值1,
'属性名2':值2,
'功能名1':function(){...}
};
js中一切都是对象!所有对象的底层都是hash数组
属性:如何访问属性:2种:obj.属性名或obj["属性名"]
访问对象中不存在的属性(访问数组中不存在的下标):不会出错,返回undefined
如何判断某个对象是否包含指定成员:3种
(1)obj.hasOwnProperty("成员名"),如果找到,返回true,否则返回false!
(2)"属性名" in 对象,如果找到,返回true,否则返回false!
(3)直接使用obj.属性名作为条件:arr.indexOf!==undefined
如果不包含,返回undefined-->false;如果包含,返回值或function-->true
何时省略:判断方法是否存在时,如果确定属性值一定不是null,0," ",NaN,可省略!==
2、new 关键字:
var obj=new Object();//创建一个空对象
obj.属性名=值;
obj.方法名=function(){...this.属性名...}
3、利用构造函数反复创建相同结构的对象:2步:
构造函数:描述一类对象结构的特殊函数
(1)定义构造函数
function 构造函数名|类型名(属性参数1,...){
this.属性名=属性参数1;
if(!构造函数名.prototype.方法名){
构造函数名.prototype.方法名=function(){
...this.属性名...
}
}
}
(2)利用构造函数创建对象:
var obj=new 构造函数名|类型名(属性值1,...);
new:a、创建一个空对象:new obj={ };b、用空对象,调用构造函数;c、返回新对象的地址
4、Object.create(父对象,{扩展属性的列表对象})
三、this关键字:运行时,指代正在调用方法的对象(.前的对象)
在方法内访问当前对象自己的属性,必须用this.属性名
this本质是window下唯一的一个指针,指向当前正在调用方法的对象
this和定义在哪儿无关!仅和调用时使用的当前对象有关
如果无主的调用或赋值,默认this都是window!
四、原型相关API
1、原型对象:每个函数对象都有一 个原型对象,构造函数的原型对象负责保存所有子对象共享的成员!
所有函数都有prototype,指向自己的原型对象
所有对象都有_proto_,指向自己父级原型对象
所有原型对象都有constructor,指回原型对应的构造函数
建议:所有子对象共享的方法,都应定义在构造函数的原型对象中。——避免重复定义方法对象,浪费内存。
说明:其实所有内置类型的API都是定义在类型.prototype
2、原型链:由各级对象的_proto_逐级继承形成的关系
获得任意对象的父级原型对象:Object.getPrototypeOf(子对象)==>子对象._proto_
检查对象的父对象:父对象.isPrototypeOf(子对象)
3、扩展对象属性:2种扩展:
(1)扩展共有属性:通过构造函数.prototype添加的属性
(2)扩展自有属性:通过某一个具体子对象添加的属性
4、判断自有属性或共有属性:
(1)判断自有属性:obj.hasOwnProperty("属性名")
(2)判断共有属性:"属性名" in obj && ! obj.hasOwnProperty("属性名");在原型关系中包含且子对象自己没有
5、删除属性:delete 对象.属性名;仅能删除当前对象自己的属性,无法删除共有属性
6、获得任意对象的原型:Object.getPrototypeOf(obj)
7、判断父对象是否在子对象的原型链上:父对象.isPrototypeOf(子对象)
8、全局变量:3种
var n=1;不能delete
window.n=1;不能delete
window["n"]=1;可被delete
9、检测一个对象是不是数组类型:4种
(1)Array.prototype.isPrototypeOf(obj);
(2)obj instanceof Array:对象是不是构造函数的实例
(3)obj.constructor==Array 仅判断直接父级
(4)利用当前对象,强行调用原始的toString方法
Object.prototype.toString.call(obj)=="[object Array]"
Object.prototype.toString.apply(obj)=="[object Array]"
五、继承
为什么要继承:代码重用!节省空间!
1、直接继承对象:想方设法修改对象的_proto_ 3种:
(1)仅修改一个对象的_proto_
Object.setPrototypeOf(子对象,父对象)
(2)通过修改构造函数的原型对象,实现批量修改后续子对象的继承关系
构造函数.prototypeOf=父对象
强调:仅影响之后创建的对象的继承关系,之前创建的对象依然继承旧构造函数.prototype
(3)Object.create(父对象[,{属性列表}])
创建一个空对象,继承父对象中的属性,继承同时可再扩展属性和方法。
2、仅继承结构:模拟Java中的继承
function 父类型构造函数(属性参数1,属性参数2){
this.属性1=属性参数1;
this.属性2=属性参数2;
}
function 子类型构造函数(属性参数1,参数属性2,参数属性3){
父类型构造函数.call(this,属性参数1,属性参数2);
this.属性3=属性参数3;
}
var obj=new 子类型构造函数(值1,值2,值3){}