面向对象和面向过程编程
一、面向过程:注重解决问题的步骤,分析问题需要的每一步,实现函数依次调用
二、面向对象:是一种程序设计思想。将数据和处理数据的程序封装到对象
将事物抽象成对象,研究每个对象的特征和行为。最后研究对象之间的关系,最终把事物的过程表示清楚。不管是通过面向对象过程还是面向对象,最终达到结果的目的是一样的。
三、面向对象的特性:抽象、继承、封装、多态
优点:提高代码的复用性及可维护性;
面向对象和面向过程演变
小明去餐厅吃饭
面向过程:小明走去餐厅看菜单点餐吃饭
面向对象:
1、小明(走、看、点餐、吃);
2、餐厅(菜单)
研究对象间的关系:小明.走餐厅 小明.看菜单 小明.点餐 小明.吃
类和对象概念
对象:具体的某个事物;(如:小明、哈士奇)
类:一类事务的抽象(类就是把所有对象共有的属性抽离出来);(如:人类、狗类)
对象创建
1、字面量方式
let obj = {name:"小明"}
2、构造函数
let obj = new Object()
obj.name = "小明"
3、Object.create() //对象创建完存在_proto_
工厂模式
特点:工厂模式提高代码的复用性。
function Person(name,hobby){
let obj = {}
obj.name = name
obj.hobby = function(){
console.log(hobby)
}
return obj
}
let zhangsan = Person('张三','喜欢足球')
let lisi = Person('李四','喜欢篮球')
new运算符
new运算符特点:
1、new执行函数;
2、自动创建空对象;
3、this绑定到空对象;
4、隐式返还this
通过new来改造工厂模式,使创建对象更加便捷
function Person(name,hobby){
this.name = name;
this.hobby = function(){
console.log(hobby)
}
}
let zhangsan = new Person('张三','喜欢足球')
构造函数
特点:
1、构造函数要通过new来调用,this指向实例化对象(属性与方法都属于实例化对象);
2、构造函数首字母大写;
静态成员
静态属性和方法(属于类本身)。当我们需要统计所有实例化对象的次数时,我们选择是类的属性,而不是实例化对象(this)的属性。
function Person(name){
this.name = name
this.hobby = function(){
console.log("喜欢篮球")
}
}
Person.num = 0
let zhangsan = new Person("张三")
Person.num++
let lisi = new Person("李四")
Person.num++
console.log(Person.num) //2
构造函数性能
构造函数每创建一个对象,就会在内存地址中开辟一个空间。变得更容易消耗内存,也会消
耗性能。
解决:公共空间存放公共方法,公共方法是不需要重新开辟空间。
原型prototype

特点:
1、通过new实例化出来的对象其属性和行为来自两个部分,一部分来自构造函数,另一部分来自原型。
2、当声明一个函数的时候,同时也声明了一个原型。
3、原型本身是一个对象。
4、对象属性方法查找规则;
function Person(name){
this.name = name;
}
公共空间原型
Person.prototype.hobby = function(){
console.log("喜欢篮球");
}
let zhangsan = new Person("张三");
let lisi = new Person("李四");
原型关系
zhangsan._proto_ === Person.prototype;
原型的固有属性constructor。
constructor主要是实例化对象通过哪个构造函数进行实例的,实例化对象的指向问题。也可以通过constructor来判断类型。
let str = "abc"; str.constructor === String;
Person.prototype.constructor === Person;
zhangsan.constructor === Person;
以下情况会覆盖Person.prototype中的constructor属性,需要重新指向。
Person.prototype = {
constructor:Person,
hobby:function(){
console.log("hobby")
}
}
原型构造函数及对象关系
工厂模式对比构造函数
1、没有解决对象识别的问题。即创建的所有实例都是Object类型。(不清楚是哪个对象的实例)。
2、没有原型,占用内存
原型链
对象之间的继承关系,在javascript中是通过prototype对象指向父类对象,直到指向Object对象为止,这样就形成了一个原型指向的链条,成为原型链;
1、当访问一个对象的属性或方法是,会先在对象自身上查找属性或方法是否存在,如果存在就使用自身的属性或方法。如果不存在就去创建对象的构造函数的原型对象中查找,一次类推,直到找到为止。如果到顶层对象中还找不到,则返回undefined。
2、原型链最顶层为Object构造函数的prototype原型对象,给Object.ptototype添加属性或方法可以,除null和undefined之外的所有数据类型对象使用。
继承
继承:子类继承父类所有属性和行为,父类不受影响。
原型链继承
优点:父类方法可以复用
缺点:1、父类所有引用属性会被子类共享,更改子类引用属性,其他子类也会受影响
2、子类不能向父类(超类)传参
构造函数继承
优点:1、父类引用属性不会被子类共享
2、子类可以向父类传参
缺点:子类实例不能再访问父类原型上的方法
组合继承
优点:1、父类原型上的方法可以复用
2、子类可以向父类传参
3、父类构造函数的引用属性不会被共享
缺点:
调用了凉菜父类构造函数,消耗内存。一、在创建子类原型。二、子类型构造函数内部调用
寄生式组合继承
var Link = function(){}
Link.prototype = Parent.prototype
Child.prototype = new Link()
优点:1、只调用一次父类构造函数....