面向对象的概念
面向对象程序设计(OOP)是种具有对象概念的程序编程典范。它可能包含数据、属性、方法。对象则指的是类的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高代码的重用性、灵活性和扩展性,对象里的程序可以访问及修改对象相关连的数据。
类与对象
类是一组相关的属性和行为的集合。类就是对一些具有共性特征,并且行为相似的个体的描述。(比如小李和老张都有姓名、年龄、身高、体重等一些属性,并且两人都能够进行聊天、运动等相似的行为方法。 )
属性,对象所拥有的静态特征在类中的表现被称为类的属性,即事物"拥有"什么
方法,对象执行的操作称为类的方法,即事物"能做"什么
对象是类的实例。是该类事物的具体表现形式,是具体存在的个体。
使用方法:Var 对象名 = new 类名( );
面向过程与面向对象
面向过程是一件事情“该怎么做” ,凡事亲力亲为,每件事的具体过程都要知道,注重过程。
面向对象是一件事情“该让谁做”,根据需求寻找对象,所有的是都用对象来做,注重结果。
解决问题模块:
面向过程,函数;
面向对象,对象。
解决问题中心角度:
面向过程,How,“如何做?”(流程封装为函数,“如何”就是过程,谁来做仅是参数);
面向对象,Who,“谁来做?”(“谁”就是对象,如何做是他自己的操作,多个对象协同完成任务)。
解决问题步骤角度:
面向过程,先具体逻辑细节,后抽象问题整体;
面向对象,先抽象问题整体,后具体逻辑细节。
复用层次角度:
面向过程,方法层复用;
面向对象,对象层复用。
具体代码:
// 狗吃屎
//面向过程 ---- > 吃
var name = "";
var age = "";
function eat(params) {
console.log("旺财正在吃" + params);
}
eat("粑粑");
eat("猪肉");
//面向对象 ---- > 狗
class Dog {
constructor(name, age, color) {
this.name = name;
this.age = age;
this.color = color;
}
eat(food) {
console.log(
this.name +
"是一条大" +
this.color +
"狗,今年" +
this.age +
"岁,正在吃" +
food
);
}
}
let dahuang = new Dog("大黄", "2", "黄");
let xiaohei = new Dog("小黑", "3", "黑");
dahuang.eat("牛排");
xiaohei.eat("骨头");
再举个例子:
把大象装进冰箱。
面向过程的方法:
1、开门(冰箱)
2、装进(冰箱,大象)
3、关门(冰箱)
面向对象的方法:
1、冰箱.开门( )
2、冰箱.装进(大象)
3、冰箱.关门( )
由此可以看出:
面向过程是以动词为主,完成一个事件就是将不同的动作函数按顺序调用。
面向对象是以主谓为主,将主谓看成一个个对象,然后对象有自己的属性和方法。如冰箱有自己的id属性,有开门、装东西、关门等方法。然后可以直接调用冰箱的装东西方法并给其传入一个参数大象即可。
面向对象三要素
继承:
继承可以将公共的方法抽离出来,提高复用、减少冗余。子类继承父类。
代码示例:
//父类
class People {
constructor(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
say(message) {
console.log(message);
}
}
//子类 子类继承父类 , 父类的功能 子类可以继承
class Child extends People {
constructor(name, age, sex) {
super(name, age, sex);
}
say(){
console.log("我会说中文");
}
fly() {
console.log("俺会飞!");
}
}
class Child1 extends People {
constructor(name, age, sex) {
super(name, age, sex);
}
say(){
console.log("我会说英文");
}
fly() {
console.log("俺会飞!");
}
}
let zhangsan = new child();
zhangsan.say("都是石头里面蹦出来的,为啥他是猴子!");
zhangsan.fly();
封装:
封装有三个属性 (ES6不支持,可以TS演示)
Public 完全开放
Protected 对子类开放
Private 对自己开放
可以用于数据权限和保密
封装的特点:
1.减少耦合,不该外露的不外露
2.利于数据的权限管理
3.ES6目前不支持,一般默认用_开头的属性是private
代码示例:
class People {
// ES6通过constructor()方法 ,构造器来实现
public name: string;
public age: number;
constructor(name: string, age: number) {
// 实例属性
this.name = name;
this.age = age;
}
say(): void {
//void 没有返回值
console.log("我会说话!");
}
}
// 子类继承父类
class Student extends People {
public num: string;
constructor(name: string, age: number, num: string) {
super(name, age);
this.num = num;
}
study(): void {
console.log(`我的名字叫${this.name},年龄是${this.age}`);
}
}
const stuA = new Student("李强", 5, "A1");
stuA.study();
console.log(stuA.name);
// 因为此时name是public公开的,所以外部可以访问到,如果改成protected,就无法被外部访问了,只能被子类访问
// 封装:找到变化并且把它封装起来,你就可以在不影响其它部分的情况下修改或扩展被封装的变化部分,
// 这是所有设计模式的基础,就是封装变化,因此封装的作用,就解决了程序的可扩展性。
多态:
同一接口不同表现(js应用极少),需要结合其它强类型语言的重写、重载等功能。
ECMAScript中为什么没有函数重载概念?
因为在ES中函数都是对象,函数名实际上是一个指向函数的指针,并不与函数绑定,例如:
function add(a){ // 第一个add函数
return a+1;
}
function add(a,b){ // 第二个add函数
return a+b;
}
console.log(add(1)); // NaN
console.log(add(2,3)); // 5
上面代码中,如果是c++或者java等强类型语言,可以分别输出2和5;但是在js中,函数名仅仅只是保存了指向函数对象的指针,创建第二个函数add时,指针指向了新的函数对象,所以第一个函数并没有起任何作用。
总结
什么是面向对象?
面向对象程序设计(OOP)是种具有对象概念的程序编程典范。它是数据、属性、方法的集合。
面向对象的优点?
将对象作为程序的基本单元,将程序和数据封装其中,可以提高代码的重用性、灵活性和扩展性。
面向对象三要素?
继承、封装、多态