面向对象编程举例
- 面向过程的方式去实现功能 DRY
- 使用函数进行了封装
- 使用面向对象的方式进行封装
面向对象的三大特性
封装
将属性和方法,封装起来,在对象内部实现某些功能,对外界之暴露接口,外界在适用对象的时候,只需要关心接口的使用,而不需要关心对象内部功能的具体实现
继承
自己没有的东西,别人有,拿过来使用,就是继承。(拿来主义)
多态
父类指针指向子类对象(JS中不支持多态)
创建对象的三种方式
字面量方式
1 | var obj = { |
缺陷:复用性差!!
内置构造函数
1 | var obj = new Object(); |
缺陷:复用性差!!
自定义构造函数
自定义构造函数
构造函数的概念
构造函数也是函数,他是用来初始化对象的!
构造函数的特点
* 首字母大写
* 一般和new关键字一起使用
* 不需要手动写返回值
构造函数的执行过程
1. 使用new关键字创建对象
2. 调用构造函数
3. 将构造函数内部的this指向new创建出来的对象
4. 在构造函数内部使用this为对象新增成员
5. 返回该对象
构造函数的使用注意事项
* 返回值:不需要手动写返回值,如果写了
* 如果是值类型的,将不会对返回值有任何的影响
* 如果是引用类型的,则会将默认返回值进行替换
* 如果把构造函数当做普通函数调用,this会指向window,返回值如果不写,会是undefined
原型
原型是什么?
构造函数在创建出来的时候,系统会默认的帮构造函数创建并且关联一个空的对象,这个对象就是原型
原型的作用?
原型中的成员可以被和其关联的构造函数所创建出来的所有的对象共享!
原型的访问方式
- 构造函数.prototype
- 对象.proto (不推荐使用,因为非标准,有兼容性问题)
原型的使用
- 利用对象的动态特性,为原型对象新增成员
- 直接替换原型对象
原型的使用注意事项
- 一般情况下将方法放在原型中,将属性放在对象中
- 当访问对象的属性的时候,会先在对象自身中查找,如果没有会去原型中查找
- 当替换原型对象的时候,替换之前所创建的对象和替换之后创建的对象的原型不一致!
- 对象的原型就是创建对象那一刻构造函数所关联的那个原型
- 设置对象的属性的时候,不会去原型中进行查找,只会在自身设置
constructor
原型中的一个属性,指向和原型相关的构造函数!
在替换原型对象的时候,这个constructor属性就不准确,所以会手动进行补充
继承的实现方式
混入式继承(mix-in)
1 | var obj = {}; |
原型继承
- 利用混入的方式为原型对象添加成员
1 | function Person(){ |
- 直接替换原型对象
1 | function Person(){ |
经典继承
经典继承的根本,其实还是原型继承!1
2var obj = Object.create(obj1);
//创建一个对象obj,obj的原型是obj1
经典继承的兼容性处理1
2
3
4
5
6
7
8
9function myCreate(obj){
if(Object.create){
return Object.create(obj);
}else{
function F(){}
F.prototype = obj;
return new F();
}
}
原型链
在js中,对象都有原型,原型也是对象,所以原型也有原型,那么就形成了链式结构,称作原型链!
属性搜索原则
- 在对象访问成员的时候,会现在自身进行查找,如果找到了就直接使用
- 如果没有找到,就去对象的原型中进行查找,如果找到了就直接使用
- 如果没有找到,就沿着原型链,依次向上查找,直到null
Object.prototype的成员
名称 | 说明 |
---|---|
constructor |
指向和原型相关的构造函数 |
hasOwnProperty |
判断对象本身是否拥有某个属性 |
isPrototypeOf |
判断对象是不是另外一个对象的原型对象 |
propertyIsEnumerable |
判断属性是否属于对象自身并且可以被遍历 |
toString |
将对象转成字符串 |
toLocaleString |
将对象转成本地格式的字符串 |
valueOf |
当值类型和引用类型参与运算的时候,会调用引用类型的valueOf方法,如果返回值还不能参与运算就去调用toString方法 |
__proto__ |
指向对象的原型对象 |