[ES6]Day06—ES6中的类与对象

ECMAScript 6 入门 (Day06)

接上篇:[ES6]Day05—Set 和 Map 数据结构

[ES6]Day06—ES6中的类与对象_第1张图片

6.1 面向过程编程与面向对象编程

6.1.1 面向过程编程 POP(Process-oriented Programming)

面向过程 :分析出解决问题所需步骤,然后用函数把这些步骤一步一步实现,使用时再一个一个的依次调用就行了

举个例子:将大象装进冰箱,面向过程做法

  1. 打开冰箱门
  2. 大象装进去
  3. 关上冰箱门

6.1.2 面向对象编程 OOP(Object-oriented Programming)

面向对象 :把事务分解成为一个个对象,然后由对象之间分工与合作

举个例子:将大象装进冰箱,面向对象做法

  1. 大象对象
    - 进去
  2. 冰箱对象
    - 打开
    - 关闭
  3. 使用大象和冰箱的功能

在面向对象程序开发思想中,每一个对象都是功能中心,有明确的分工。
面向对象编程具有灵活、代码可复用、容易维护和开发的优点,更适合多人合作的大型软件项目。

面向对象的特性:

  • 封装性
  • 继承性
  • 多态性

[ES6]Day06—ES6中的类与对象_第2张图片

6.1.3 面向过程和面向对象对比

面向过程 面向对象
优点 性能比面向对象高,适合跟硬件联系紧密的东西,例如单片机采用的是面向过程编程 易维护、易复用、易拓展,由于面向对象具有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更易维护
缺点 没有面向对象易维护、易复用、易拓展 性能比面向过程低

一句话概括:面向过程得到一份蛋炒饭,面向对象得到的是一份盖浇饭。

6.2 ES6中的类与对象

6.2.1 对象

  • 定义: 对象是一个具体的事物,看得见摸得着的实物。
  • 在JavaScript中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。

对象是由属性和方法组成的:

  • 属性:事物的特征,在对象中用属性来表示(常用名词)
  • 方法:事物的行为,在对象中用方法来表示(常用名词)

6.2.2 类Class

  • ES6新增类的概念,使用Class关键字声明一个类,之后以这个类来实例化对象。

泛指某一大类(class),抽象了对象的公共部分
对象特指某一个,通过类实例化一个具体的对象

语法class 类名{ }

//1.创建一个名为 Star 的类
class Star{
	constructor(uname){
		this.uname=uname;
	}
}

//2.利用类创建对象 
var hh= new Star('易烊千玺');
console.log(hh.uname);//易烊千玺

ES6 的类,完全可以看作构造函数的另一种写法。

class Point {
  // ...
}

typeof Point // "function"
Point === Point.prototype.constructor // true

上面代码表明,的数据类型就是函数本身就指向构造函数

class Point {
  constructor() {
    // ...
  } 
  toString() {
    // ...
  } 
  toValue() {
    // ...
  }
}

// 等同于

Point.prototype = {
  constructor() {},
  toString() {},
  toValue() {},
};

在类的实例上面调用方法,其实就是调用原型上的方法。

class B {}
let b = new B();

b.constructor === B.prototype.constructor // true

上面代码中,b是B类的实例,它的constructor方法就是B类原型的constructor方法。

6.2.3 类的constructor方法

  1. constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。
  2. 一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
class Point {
}

// 等同于
class Point {
  constructor() {}
}
  1. constructor方法默认返回实例对象(即this),完全可以指定返回另外一个对象
class Foo {
  constructor() {
    return Object.create(null);
  }
}

new Foo() instanceof Foo
// false

constructor函数返回一个全新的对象,结果导致实例对象不是Foo类的实例。

6.2.4 类中添加方法

语法:直接在类里加 方法名{}

class Person{
	constructor(name,age){ // constructor 构造器或者构造函数
		this.name=name;
		this.age=age; 
	}
	say(){
		console.log(this.name+'你好呀~')
	}
	//,报错,Unexpected token ','
	sing(song){
		console.log(this.name+'唱'+song);
	}
}

var ww=new Person('ww',21);
var hh=new Person('hh',23);
ww.say()
hh.say()
ww.sing('栀子花开~')
hh.sing('洗刷刷~') 

[ES6]Day06—ES6中的类与对象_第3张图片
注意:

  1. 类里面所有函数不用加function
  2. 多个函数方法之间不需要添加逗号分隔

6.3 类的继承

6.3.1 继承

现实中的继承:子承父业,比如我们都继承父亲的姓氏
程序中的继承:子类可以继承父类的一些属性和方法

语法:使用 extends 关键字

class Father{//父类
	constructor(name,age){ // constructor 构造器或者构造函数
		this.name=name;
		this.age=age; 
	}
	money(){
		console.log(100)
	}
	say(){
		console.log('自我介绍~我叫'+this.name+'今年'+this.age+'岁')
	}   
}
class Son extends Father{//子类继承父类
	constructor(name,age){ // constructor 构造器或者构造函数
		this.name=name;
		this.age=age; 
	}
}  
var son =new Son()
son.money();   //100 

6.3.2 super 关键字

super 关键字用于访问和调用对象父类上的函数,可以调用父类的构造函数,也可以调用父类的普通函数

//调用父类的构造函数

class Father{//父类
	constructor(x,y){ 
		this.x=x;
		this.y=y; 
	}
	sum(){
		console.log(this.x+this.y)
	}
	    
}
class Son extends Father{//子类继承父类
	constructor(x,y){ 
		super(x,y);//调用了父类中的构造函数
		this.x=x; //定义子类独有的属性
		this.y=y; //定义子类独有的属性
	}
}  
var son =new Son(1,2)
son.sum();   //3

1.在子类的constructor方法中,super(x,y)调用了父类中的构造函数

//调用父类的普通函数

class Father{//父类 
	say(){
		console.log('我是爸爸')
	}
	    
}
class Son extends Father{//子类继承父类
	 say(){
	 	// console.log('我是儿子');
	 	 
	 	console.log(super.say()+`的儿子`);
	 	// super.say()直接调用父类的普通函数say()
	 }
}  
var son =new Son()
son.say();//我是爸爸的儿子
var son =new Son()
son.say();

son.say(),查找子类有没有say(),有,先执行子类中的say()方法,如果子类中没有,就去查找父类有没有这个方法,有则调用父类的say()方法。

  1. 继承中的属性方法查找采用就近原则

  2. super.say()直接调用父类的普通函数say()

//子类拓展自己的方法

class Father{ //父类
	constructor(x,y){ 
		this.x=x;
		this.y=y; 
	}
	sum(){
		console.log(this.x+this.y)
	}
	    
}
class Son extends Father{//子类继承父类
	constructor(x,y){ 
	
	//利用super 调用父类中的构造函数
	//super必须在子类this之前调用 
		super(x,y);
		this.x=x; //定义子类独有的属性
		this.y=y; //定义子类独有的属性
	}
	subtract(){ //子类拓展方法
		console.log(this.x-this.y)
	}
}  
var son =new Son(8,2)
son.sum();   //10
son.subtract(); //6

注意:子类在构造函数中使用super,必须在子类this之前调用,(必须先调用父类的构造方法,在使用子类构造方法)

6.3.3 使用类注意事项

var s=new Son(1,2);
s.sum(); //报错,Son is not defined,需要把实例化放在定义的后面

class Son{
	constructor(x,y){ 
		this.x=x;
		this.y=y; 
		//sum();报错,sum is not defined
		this.sum(x,y)
	}
	sum(){
		console.log(this.x+this.y)
		// console.log(x+y) 报错,x is not defined
	}
}
  1. 在ES6中类不存在变量提升,所以必须先定义类,才能通过类实例化对象
  2. 类中的共有属性和方法一定要加this关键字
  3. 类里面this 指向问题
  • constructor里的 this ,指向创建的实例对象
  • 方法里的this,谁调用了dance 函数,this就指向谁
var that,_that;
class Star{
	constructor(uname){
	//constructor里的this,指向创建的实例对象:hh
		that=this;
		console.log(this)
		
		this.uname=uname;

		this.btn=document.querySelector('button');
		//this.btn的点击事件调用了sing()
		this.btn.onclick=this.sing;
	}
	sing(){
	
		//这里的this,指向button对象,因为其点击事件调用了sing()
		console.log(that.uname)//易烊千玺,that里面存储的是constructor里的this
		console.log(this.uname)//报错,button对象无uname属性
	}
	dance(){ 
		//方法里的this,谁调用了dance函数,this就指向谁
		
		_that=this;
		console.log(this);
	}
}

//实例化 
var hh= new Star('易烊千玺'); 
console.log(that===hh);// true

hh.dance()
console.log(_that===hh);// true

原文链接:

阮一峰:ECMAScript 6 入门

你可能感兴趣的:(ES6)