面向对象
面向对象介绍
上世纪 70 年代,图灵奖获得者Alan Curtis Kay(艾伦·凯)提出了面向对象的思想,可以说,他是面向对象思想的鼻祖。图灵奖由美国计算机协会(ACM)于 1966 年设立,专门奖励那些对计算机事业作出重要贡献的个人。一般每年只奖励一名计算机科学家,只有极少数年度有两名合作者或在同一方向作出贡献的科学家共享此奖。因此它是计算机界最负盛名、最崇高的一个奖项,有“计算机界的诺贝尔奖”之称。
在《面向对象分析与设计》这本书中,Grady Booch(格雷迪.布奇) 总结认为,从人类的认知角度来说,对象应该是下列事物之一:
- 一个可以触摸或者可以看见的东西;
- 人的智力可以理解的东西;
- 可以指导思考或行动(进行想象或施加动作)的东西。
有了对象的自然定义后,我们就可以描述编程语言中的对象了。在不同的编程语言中,设计者也利用各种不同的语言特性来抽象描述对象,最为成功的流派是使用“类”的方式来描述对象,这诞生了诸如 C++、Java 等流行的编程语言。而 JavaScript 早年却选择了一个更为冷门的方式:原型。
**面向过程: ** 把问题步骤化、过程化,按照一定的步骤一步一步的去执行,达到最终的目标。
比较好理解,但是,当遇到一个大型的项目时,步骤十分繁重复杂。而且,一旦一个步骤或一个环节出现问题,整个过程就无法继续。
ES6的面向对象
根据《面向对象分析与设计》总结来看,对象有如下几个特点。(唯一、状态、行为)
-
对象具有唯一标识性:即使完全相同的两个对象,也并非同一个对象。
-
有状态:对象具有状态,同一对象可能处于不同状态下。
-
对象具有行为:即对象的状态可能因为它的行为产生变迁。
对于第一个特性“唯一标识性”,这一点我们早就知道了,任意两个对象在JavaScript里面都不会相等。关于对象的第二个和第三个特征“状态和行为”,不同语言会使用不同的术语来抽象描述它们,比如 C++ 中称它们为“成员变量”和“成员函数”,Java 中则称它们为“属性”和“方法”。
在 JavaScript 中,将状态和行为统一抽象为“属性”。在js的对象里面,属性的内容不同就可以表示面向对象里面的“状态”和“行为”
静态和动态特征之间有没有关系?肯定有,动态的特征都是建立在静态特征基础上的,否则无法产生动态效果;实际上动态特征的不同都是静态属性的变化引起的。比如跑和跳都是由腿和脚的各种变化引起的。
js中的对象具有高度动态性,因为js赋予了使用者为对象添改状态和行为的能力
class类
关键词:类 对象 属性 方法
对象: 实例化一个对象。把一个抽象的的事物,变成一个实实在在的例子。(把一个类进行实例化之后就产生了对象)(人类:张三、李四。狗类:旺财)
类: 对一批具有相同属性和行为的事物的抽象。抽象的意思就是看不见也摸不着的。类是来描述属性和行为的
类的特征: 类是一种封装
基本语法
// 人类
class Person{
name = "Jerry";
age = 18;
height = "180cm";
say(){
console.log("I am a person");
}
}
// 实例化一个Jerry
let p1 = new Person()
console.log(p1);//Person {name: "Jerry", age: 18, height: "180cm"}
问题:这种基本写法,是没有办法传参的
constructor方法
constructor方法是类的内置方法
这个方法和其他方法不一样,不是让开发者调用的,而是在new实例化对象时自动被调用的
constructor就是构造方法,用于对象的属性或方法初始化
// 人类
class Person{
constructor(name, age, height){
// 所有的属性,都放在constructor 这个函数里面
// 当new实例化时,constructor会自动调用(不用手动调用)
this.name = name;
this.age = age;
this.height = height;
}
// 方法都直接放在类里就行
say(){
console.log(this + "I am a person");
}
}
// 实例化一个Jerry
let p1 = new Person("Jerry", 18, "180cm")
console.log(p1);//Person {name: "Jerry", age: 18, height: "180cm"}
// 实例化一个Mary
let p2 = new Person("Mary", 19, "160cm")
console.log(p2);//Person {name: "Mary", age: 19, height: "160cm"}
每一个对象都具备类的属性和方法的独立拷贝
成员和静态
由对象调用的属性和方法叫成员属性和成员方法
由类调用的属性和方法就静态(类)属性和静态(类)方法
// 成员属性:由成员(对象)调用的属性
// 成员方法:由成员(对象)调用的方法
// 静态(类)属性:由类调用的属性,叫静态属性
// 静态(类)方法:由类调用的方法,叫静态方法
//当这个属性或者方法的值是共有的,那么我们就使用静态的。如果每个值都是自己私有的,那么就用成员的
class Person{
// 静态属性,需要写到类里面,还需要使用static 去修饰
static state="live"
constructor(name, age, height){
//这里的属性都是成员属性,也就是,只有具体的对象才能调用
this.name = name;
this.age = age;
}
// 这个say是成员方法,只有具体的对象才能调用
say(){
console.log("I am a person and my name is" + this.name);
}
static run(){
console.log("Person run");
}
}
//调用成员
let p1=new Person("Jerry", 18)
console.log(p1.name);
p1.say()
// 调用静态
console.log(Person.state);
Person.run()
es6继承
extends
class Person{
static state="live"
constructor(name, age){
this.name = name;
this.age = age;
}
say(){
console.log("I am a person and my name is "+this.name);
}
static run(){
console.log("Person run");
}
}
class Student extends Person{
}
let s1 = new Student("Jerry",18)
console.log(s1.name);
console.log(s1.age);
s1.say()
console.log(Student.state);
Student.run()
super
super() 写到constructor里面,去调用父类的属性
super.方法() 写到自定义方法里面,去调用父类的方法
class Person{
static state = "live";
constructor(name, age){
this.name = name;
this.age = age;
}
say(){
console.log("I am a person and my name is "+this.name);
}
static run(){
console.log("Person run");
}
}
class Student extends Person{
// 属性名相同会覆盖
static state =" study";
constructor(name, age, course, age1){
// console.log(name,age,course);
// 在constructor里面,需要使用super方法去继承父类的成元素属性
super(name, age)/// super调用的就是父类的constructor
this.course = course;
this.age = age1//如果子类的属性和父类重名,会覆盖
}
say(){
// 如果子类方法和父类方法重名,那么会覆盖,但是,可以通过super对象去调用父类的方法
super.say()
console.log("I am a student and my name is "+this.name);
}
static run(){
// 如果子类方法和父类方法重名,那么会覆盖,但是,可以通过super对象去调用父类的方法
super.run()
console.log("Student run");
}
}
let s2=new Student("小姜", 20, "Web Development", 24)
console.log(s2.name);
console.log(s2.age);
console.log(s2.study);
s2.say()
console.log(Student.state);
Student.run()