面向对象开发方式 - 三大特点(封装、继承、多态) 什么是面向对象:在程序中都使用对象来描述现实中的一个事物 现实中事物的属性,代码中就成为了对象的属性 现实中事物的方法,代码中就成为了对象的函数 现实中所有数据都必须包含在一个事物中才有具体的意义
之前我们学的10个引用类型都是对象 - 浏览器内置对象
1、封装/创建/定义/声明/实例化:自定义创建对象:3种
1、*直接量方式:
var obj={
"属性名":属性值,
...
"方法名":function(){},
...
}
强调:1、其实属性名和方法名的""可以省略,但是不推荐,以后JSON必须加""
2、如何访问对象属性和方法
obj.属性名 === obj["属性名"]
obj.方法名(); === obj["方法名"]();
强烈建议:使用.去访问
3、访问到不存在的属性:返回undefined
4、也可以在后续随时随提的添加自己想要的东西
特殊:this在当前对象的方法内,指向的当前调用方法对象
面试题:this指向:
1、单个元素绑定事件 this->单个元素
2、多个元素绑定事件 this->当前触发的元素
3、函数中也可以使用 this->当前调用函数的对象
4、构造函数中如果出现了this this->当前正在创建的对象
只要以后对象的方法想要使用对象自己的属性,那么就写为this.属性名
2、预定义构造函数:var obj=new Object();//空对象
obj.属性名=属性值;
...
obj.方法名=function(){}
...
以上两个方法仅适合创建单个对象,如果想要创建多个对象则太繁琐
3、*自定义构造函数:2步
1、创建一个构造函数
function 类名(形参,...){
this.属性名=形参1;
this.属性名=形参2;
...
}
2、反复调用构造函数创建出多个对象
var xxx=new 类名(实参,...)
面试:聊一聊你了解面向对象和面向过程的开发方式? 1、面向过程:开始->经过->结束,我们一直使用的开发方式。 2、面向对象:对象:属性和方法 一个人是一个对象 属性: 身高 体重 年龄 姓名 三维 方法: 吃饭 睡觉 拉屎 玩耍 所有的属性和方法全都是包含在一个对象中的,比如:轮播对象、选项卡对象...
优:1、逼格高
2、所有的操作都包含在一个对象中,显得更有意义
3、维护时非常的舒服
4、铁索连舟 - 一个方法调用,触发了一大堆操作
缺:1、难度大 - this的指
继承:父对象的成员(属性和方法):子对象可以直接使用 为什么继承:代码重用!节约内存空间! 何时继承:只要多个子对象公用的属性和【方法】,都应该集中定义在父对象中
JS的面向对象是基于原型(父对象)的
什么是原型:保存一类子对象共有属性和共有方法的原型对象(父对象)
1、如何去找到原型对象:
1、对象名.__proto__ - 至少要创建一个对象才可以使用
2、构造函数名.prototype
new 构造函数(Object RegExp Date Function String Number Boolean...)
2、在原型对象中添加共有属性和共有方法
原型对象.属性名=属性值
原型对象.方法名=function(){}
每一个对象都有一个.__proto__的属性指向着自己的原型
每一个构造函数都有一个.prototype属性指向着自己的原型
面试题:两链一包:
原型链:自己没有的属性和方法,可以顺着原型链一直向上找,直到最顶层:Object.prototype - 万物皆对象
作用:查找属性和方法
自有和共有
自有:保存在对象本地的
共有:保存在原型对象中的,子对象都可以直接使用
一大批鄙视题:
1、判断一个属性是自有还是共有:
1、判断自有:obj.hasOwnProperty("属性名");
如果结果为true,说明是自有
如果结果为false,可能是共有也可能是没有
2、判断共有:2个条件
obj.hasOwnProperty("属性名")==false;//可能是共有也可能是没有
"属性名" in obj;//in关键字会查找自己的原型
if(obj.hasOwnProperty("属性名")==false && "属性名" in obj){
console.log("共有")
}else{
console.log("没有")
}
完整的:
if(obj.hasOwnProperty("属性名")){
console.log("自有");
}else{
if(obj.hasOwnProperty("属性名")==false && "属性名" in obj){
console.log("共有")
}else{
console.log("没有")
}
}
2、修改/删除属性
自有:修改:obj.属性名=新值;
删除:delete obj.属性名;
共有:修改:千万不要在本地做操作,那会导致在本地添加上一个同名属性,优先使用自己的,但并没有修改原型对象
删除:千万不要在本地做操作,那会导致白做没有任何效果
强调:一定要找到原型再做操作
3、为一类人添加方法:
比如:最常见的一道题:为老IE的数组添加indexOf方法 - 原本只有字符串可以使用,是后续升级数组才能使用的
if(Array.prototype.indexOf === undefined){//老IE
Array.prototype.indexOf = function(key,starti){
starti===undefined&&(starti=0);
for(var i=starti;i<this.length;i++){
if(this[i]==key){
return i;
}
}
return -1;
}
}
比如:为一人添加共有方法
构造函数名.prototype.函数名=function(){
this->函数中的代表当前调用此函数的对象
}
4、判断x是不是一个数组:4种
1、判断当前x对象是否是继承自Array.prototype的
Array.prototype.isPrototypeOf(x);
true说明是一个数组
2、判断当前x对象是否是由此构造函数所创建
x instanceof Array
true说明是一个数组
3、Array.isArray(x); - 只有数组才有此方法
true说明是一个数组
4、最麻烦,但是我个人最喜欢
在Object的prototype中保存着最原始的toString方法
原始的toString输出的结果:[object 构造函数名]
***多态:子对象觉得父对象提供的方法不好用,可以再本地定义一个同名成员,优先使用离自己更近的方法
同一个函数名,但根本不是同一个方法
固定套路:
if(Object.prototype.toString.apply(arr)==="[object Array]"){
数组
}
5、如何设置自定义继承
设置单个对象的继承:
obj.__proto__=新对象
设置多个对象的继承:
构造函数名.prototype=新对象
注意时机:在创建对象之前就设置好父对象