一、面向对象的编程介绍
1. 面向过程编程pop
-
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一 步实现 ,使用的时候再一个一 个的依次调用就可以了。
-
例子:将大象装进冰箱,面向过程做法。
1.开冰箱门2.把大象放进去
3.关上冰箱门
2. 面向对象编程oop
-
把事务分解成一个个对象,然后由对象之间分工与合作
-
例子:将大象装进冰箱,面向对象做法。
先找出对象,并写出这些对象的功能:
1.大象对象
进去2.冰箱对象
打开
关闭3.使用大象和冰箱的功能
在面向对象程序开发思想中,每一一个对象都是功能中心,具有明确分工。
面向对象编程具有灵活、代码可复用、容易维护和开发的优点,更适合多人合作的大型软件项目。
面向对象的特性:
-
封装性
-
继承性
-
多态性
3. 面向过程和面向对象的对比
二、ES6中的类和对象
1. 对象
对象是由属性和方法组成的:
属性:事物的特征,在对象中用属性来表示(常用名词)
方法:事物的行为,在对象中用方法来表示(常用动词)
2. 方法
在ES6中新增加了类的概念,可以使用class关键字声明一个类,之后以这个类来实例化对象。
3. 创建类
语法:
class name {
//class body
}
创建实例:
var xx = new name();
4. 类 constructor 构造函数
-
constructor()
方法是类的构造函数(默认方法),用于传递参数,返回实例对象, -
通过 new 命令生成对象实例时,自动调用该方法。
-
如果没有显示定义, 类内部会自动给我们创建一个constructor()。
<script>
//1.创建类 class 创建一个明星类
class Star {
constructor(uname,age){//类里面的构造函数
this.uname = uname;
this.age = age;
}
}
//2.利用类创建对象new
var ldh= new Star('刘德华',18);
var zxy= new Star('张学友',20);
console.log(ldh);
console.log(zxy);
</script>
5. 类中添加方法
//1.创建类 class 创建一个明星类
class Star {
//类的共有属性放到 constructor 里面
constructor(uname,age){//类里面的构造函数
this.uname = uname;
this.age = age;
}
say(){
console.log(this.uname + '你好');
}
}
6. 继承
子类可以继承父类中的一些属性和方法。
class Father{//父类
constructor(){
}
money(){
console.log(100);
}
}
class Son extends Father{//子类继承父类
}
var son = new Son();
son.money();
6.1 super关键字
super 关键字用于访问和调用对象父类上的函数,可以调用父类的构造函数,也可以调用父类的普通函数。
1. 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);//调用了父类中的构造函数
}
}
var son = new Son(1,2);
var son1 = new Son(11,22);
son.sum();
son1.sum();
2. super 关键字 调用父类的普通函数
语法:
//super关键字调用父类普通函数
class Father {
say(){
return '我是爸爸';
}
}
class Son extends Father {
say(){
// console.log('我是儿子');
console.log(super.say()+'的儿子');
// super.say()就是调用父类中的普通函数 say()
}
}
var son = new Son();
son.say();
-
继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
-
继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)
3.super必须放到子类this之前
<script>
//父类有加法方法
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(5,2);
son.sum();
son.subtract();
</script>
注意:子类在构造函数中使用super,必须放到this前面(必须先调用父类的构造方法,再使用子类构造方法)
7. ES6中的类和对象使用时的三个注意点
三个注意点:
-
在ES6中类没有变量提升,所以必须先定义类,才能通过类实例化对象
-
类里面的共有属性和方法一定要加 this 使用
-
类里面的 this 指向问题:
-
constructor 里面的 this 指向创建的实例对象,
-
方法里面的 this 指向这个方法的调用者
father.sum();//调用者是father
this.sum();//调用者是this
this.btn.onclick = this.sum;//调用者是btn
-
<button>click</button>
<script>
var that
class Father {
constructor(x, y) {
that = this;//这里的that===this
this.x = x;
this.y = y;
// this.sum();//实例化时直接调用该方法
this.btn = document.querySelector('button')
this.btn.onclick = this.sum;//加了()后会立即调用,而不是点击后调用
}
sum() {
console.log(that.x + that.y);//这里的that就是实例对象
}
}
var father = new Father(1, 5)
father.sum();
</script>
三、构造函数和对象
在ES6之前,对象不是基于类创建的,而是用一种称为构造函数的特殊函数来定义对象和它们的特征。
创建对象可以通过以下三种方式:
-
对象字面量
-
new Object()
-
自定义构造函数
1.构造函数
构造函数是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与new一起使用。我们可以把对象中一些公共的属性和方法抽取出来 ,然后封装到这个函数里面。
在JS中,使用构造函数时要注意以下两点:
-
构造函数用于创建某一类对象,其首字母要大写
-
构造函数要和new一起使用才有意义
<script>
//1.利用new Object()创建对象
var obj1 = new Object();
//2.利用对象字面量创建对象
var obj2 = {};
//3.利用构造函数创建对象
function Star(uname,age){
this.uname = uname;
this.age = age;
this.sing = function(){
console.log('sing');
}
}
var ldh = new Star('刘德华',20);
console.log(ldh);
ldh.sing();
</script>
2.构造函数中的一些成员
JavaScript的构造函数中可以添加一些成员,可以在构造函数本身上添加,也可以在构造函数内部的this上添加。通过这两种方式添加的成员,就分别称为静态成员和实例成员。
-
静态成员:在构造函数本身上添加的成员称为静态成员,只能由构造函数本身来访问
-
实例成员:在构造函数内部创建的对象成员称为实例成员,只能由实例化的对象来访问
<script>
//构造函数中的属性和方法我们称为成员,成员可以添加
function Star(uname,age){
this.uname = uname;
this.age = age;
this.sing = function(){
console.log('sing');
}
}
var ldh = new Star('刘德华',18);
//1.实例成员就是构造函数内部通过this添加的成员 uname age sing 就是实例成员
//实例成员只能通过实例化的对象来访问
console.log(ldh.uname);
console.log(Star.uname);//不可以通过构造函数来访问实例成员
//2.静态成员 在构造函数本身上添加的成员 sex就是静态成员
Star.sex = '男';
//静态成员只能通过构造函数来访问
console.log(Star.sex);
console.log(ldh.sex);//不能通过对象来访问
</script>
3. 构造函数和原型
3.1构造函数的问题
会存在浪费内存的问题
3.2 构造函数原型 prototype
构造函数通过原型分配的函数是所有对象所共享的。
-
JavaScript规定,每一个构造函数都有一个prototype属性,指向另一个对象。
-
注意这个prototype就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。
-
我们可以把那些不变的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法
<script>
function Star(uname,age){
this.uname = uname;
this.age = age;
}
Star.prototype.sing = function(){
console.log('我会唱歌');
}
var ldh = new Star('刘德华',18);
var zxy = new Star('张学友',19);
ldh.sing();
console.log(ldh); //对象身上系统自动添加一个_proto_指向我们构造函数的原型对象prototype
console.log(ldh._proto_ === Star.prototype);
//方法的查找规则:首先看ldh对象身上是否有sing方法,如果有就执行这个对象上的sing
//如果没有sing这个方法,因为有_proto_的存在,就去构造函数原型对象prototype身上去查找sing这个方法
</script>
对象都会有一个属性_ proto_ 指向构造函数的 prototype原型对象,之所以我们对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有_ proto_ 原型的存在。
3.3 constructor 构造函数
-
对象原型(_ proto_ ) 和构造函数( prototype )原型对象里面都有一个属性constructor属性,
-
constructor我们称为构造函数,因为它指回构造函数本身。
Star.prototype = {
constructor:Star,//利用constructor 属性指回原来的构造函数
sing:function(){
console.log('我会唱歌');
},
movie:function(){
console.log('我会演电影');
}
}
var ldh = new Star('刘德华',18);
var zxy = new Star('张学友',19);
console.log(Star.prototype);
console.log(ldh._proto_);
console.log(Star.prototype.constructor);
console.log(ldh._proto_.constructor);