Object:面向对象开发方式 - 三大特点(封装、继承、多态)
什么是面向对象:在程序中都使用对象来描述现实中的一个事物
现实中事物的属性,代码中就成为了对象的属性
现实中事物的方法,代码中就成为了对象的函数
现实中所有数据都必须包含在一个事物中才有具体的意义
面向对象(Object-Oriented,简称OOP)是一种编程范式,它以对象(Object)为核心,将数据(即对象的属性,有时称为成员变量或字段)和操作这些数据的方法(即对象的行为,有时称为成员函数或方法)封装在一起,以此作为程序的基本单元。面向对象编程旨在模拟现实世界中的实体和它们之间的关系,通过抽象、封装、继承和多态四个基本原则来设计和实现软件。
10个引用类型都是对象(String/Number/Boolean/Array/Function/Math/Date/RegExp/Error/Object) - 浏览器内置对象
1、封装/创建/定义/声明/实例化:自定义创建对象:3种
封装意味着将对象的状态(属性)和行为(方法)捆绑在一起,并对外界隐藏内部细节,仅通过对象提供的公共接口与外界交互。这有助于减少代码间的耦合度,增强模块性。
1、*直接量方式:
var obj={
"属性名":属性值,
...
"方法名":function(){},
...
}
强调:1、其实属性名和方法名的""可以省略,但是不推荐
2、如何访问对象属性和方法
obj.属性名 === obj["属性名"]
obj.方法名(); === obj["方法名"]();
强烈建议:使用.去访问
3、访问到不存在的属性:返回undefined
4、也可以在后续添加自己想要的东西
特殊:this在当前对象的方法内,指向的当前调用方法对象
面试题:this指向:
1、单个元素绑定事件 this->单个元素
2、多个元素绑定事件 this->当前触发的元素
3、函数中也可以使用 this->当前调用函数的对象
4、构造函数中如果出现了this->当前正在创建的对象
5、定时器中this->window
只要以后对象的方法想要使用对象自己的属性,那么就写为this.属性名
2、预定义构造函数:var obj=new Object();//空对象
obj.属性名=属性值;
...
obj.方法名=function(){}
...
以上两个方法仅适合创建单个对象,如果想要创建多个对象则太繁琐
3、*自定义构造函数:2步
1、创建一个构造函数
function 类名(形参,...){
this.属性名=形参1;
this.属性名=形参2;
...
}
2、反复调用构造函数创建出多个对象
var xxx=new 类名(实参,...)
继承:父对象的成员(属性和方法):子对象可以直接使用
继承允许一个类(子类)继承另一个类(父类)的特性和行为,从而实现代码复用,减少重复代码,并支持分层分类的概念。
为什么继承:代码重用!节约内存空间!
何时继承:只要多个子对象公用的属性和【方法】,都应该集中定义在父对象中
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=新对象
注意时机:在创建对象之前就设置好父对象
多态:
多态意味着子类可以重写或实现父类的方法,使得不同对象可以用统一的接口来调用,但表现出不同的行为。这增强了代码的灵活性和可扩展性
同一操作作用在不同对象上,可以产生不同的解释和不同的执行结果
简单说:给不同对象发送同一消息,可能会得到不同的反馈。