面向对象编程

Posted MaNqo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象编程相关的知识,希望对你有一定的参考价值。

面向对象编程

1.1 两大编程思想

  • 面向过程
  • 面向对象

1.2 面向过程编程POP(Process-oriented programming)

面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步思想,使用的时候再一一调用就可以了。

面向过程,就是按照我们分析好了的步骤。按照步骤解决问题。

  1. 打开冰箱
  2. 把大象放进冰箱
  3. 关闭冰箱

1.3 面向对象编程 OOP

面向对象是把事物分解成为一个个对象,然后由对象之间分工合作。

例子:把大象装进冰箱

先找出对象,并写出这些对象的功能

  1. 大象对象 (进去)

  2. 冰箱对象 (打开 -> 关闭)

  3. 使用大象和冰箱的功能

面向对象是以对象功能来划分问题,而不是步骤

面向对象编程具有灵活、代码可复用、容易维护和开发的特点,更适合多人合作的大型软件项目。

面向对象的特性:

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

1.4 面向过程和面向对象的对比

面向过程:

  • 优点:性能比面向对象高,适合更硬件联系很紧密的东西,例如单片机就采用面向过程的编程
  • 缺点:没有面向对象易维护、易复用、易扩展

面向对象:

  • 优点:可以设计出低耦合的系统,使系统更加灵活,更加利于维护
  • 缺点:性能比面向过程低

面向过程写出来的程序是一份蛋炒饭,而面向对象写出来的程序是一份盖浇饭。

ES6中的类和对象

面向对象

面向对象的思维特点:

  1. 抽取(抽象)对象共用的属性和行为组织(封装)成一个类(模板)

  2. 对类进行实例化,获取类的对象

用class关键字声明一个类,之后以这个类来实例化对象,类抽象了对象的公共部分,它泛指某一大类,对象特指某一个,通过类实例化一个具体的对象

2.1 创建类

语法:

class name {
    
}

创建实例:

var xx = new name()

注意:类必须使用new实例化对象

2.2 类constructor构造函数

**constructor()**方法是类的构造函数(默认方法),用于传递参数,返回实例对象,通过new命令生成对象实例时,自动调用该方法。如果没有显示定义,类内部会自动给我们创建一个constructor()>

2.3 super关键字

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

  • 继承中的属性或者方法查找原则:就近原则
  • 继承中,如果实例化之类输出一个方法,先看子类有没有这个方法,如果有就先执行之类的
  • 继承中,如果之类里面没有,就去查找父类有没有这个方法,如果有,就执行父类这个方法(就近原则)
// super关键字调用父类普通函数
class Father {
    say() {
        return 'father';
    }
}
class Son extends Father {
    say() {
        // return 'son';
        console.log(super.say()+ '的son');  // super.say()就是调用父类中的普通函数say()
    }
}
var son = new Son;
son.say();  //son 就近原则!

给子类扩展方法

// 子类继承父类加法方法 同时 扩展减法方法
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);
    }
}

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

三个注意点

  • 在ES6中类没有变量提升,所以必须先定义类,才能通过类实例化对象
  • 类里面的共有属性和方法一定要加this使用
  • 类里面的this指向问题
        var that;
        var _that;
        class Star {
    constructor(uname, age) {
        // constructor 里面的this 指向的是 创建的实例对象
        that = this;
        console.log(this);
        this.uname = uname;
        this.age = age;
        // this.sing();
        this.btn = document.querySelector('button');
        this.btn.onclick = this.sing;
    }
    sing() {
        // 这个sing方法里面的this 指向的是 btn 这个按钮,因为这个按钮调用了这个函数
        console.log(this);
        console.log(that.uname); // that里面存储的是constructor里面的this
    }
    dance() {
        // 这个dance里面的this 指向的是实例对象 ldh 因为ldh 调用了这个函数
        _that = this;
        console.log(this);
    }
}
var ldh = new Star('刘德华');
console.log(that === ldh);  //true
ldh.dance();
console.log(_that === ldh);  //true
insertAdjacenthtml(position, text)
  • beforebegin 元素自身的前面
  • afterbegin 插入元素内部的第一个子节点之前
  • beforebegin 插入元素内部的最后一个子节点之后
  • afterbegin 元素自身的后面
  1. 以前的做法:动态创建元素createElement,但是元素里面的内容较多,需要在innerHTML赋值,在appendChild追加到父元素里面

  2. 现在高级做法,利用insertAdjacentHTML()可以直接把字符串格式元素添加到父元素中

  3. appendChild不支持追加字符串的子元素,insertAdjacentHTML支持

3.1 类的本质

类的本质其实还是一个函数,我们也可以简单的认为,类就是构造函数的另外一种写法。

  • 类的原型对象有prototype
  • 类原型对象prototype里面有contructor 指向类本身
  • 类可以通过原型对象添加方法
  • 类创建的实例对象有__proto__原型指向类的原型对象
  • 类其实就是语法糖
  • 语法糖:简单理解,有2个方法可以实现同样的功能,但是一种写法更加清晰、方便,那么这个方法就是语法糖。

3.2 数组方法

迭代(遍历)方法:forEach()、、、、

a. map()

依次遍历数组成员,根据遍历结果返回一个新数组。(不会改变原始数组)。

const arr = [3,4,4,5,4,6,5,7];
const a = arr.map(item => item*2;) 
// [6, 8, 8, 10, 8, 12, 10, 14]

b. forEach()

跟 map 方法类似,遍历数组,区别是forEach()无返回值。

array.forEach(function(currentValue, index, arr))
  • currentValue:数组当前项的值
  • index:数组当前项的索引
  • arr:数组对象本身
var arr = [1, 2, 3];
var sum = 0;
arr.forEach(function(value, index, array) {
    console.log('每个数组元素' + value);
    console.log('每个数组元素的索引号' + index);
    console.log('数组本身' + array);
    sum += value;
})
console.log(sum);  // 6

c. filter()

array.filter(function(currentValue, index, arr))
  • filter()方法主要用于筛选数组
  • 直接返回一个新数组(相当于深度拷贝)
var arr = [12, 66, 4, 88, 3, 7];
var newArr = arr.filter(function(value, index) {
    // return value >= 20;  给条件
    return value % 2 === 0;
});
//var newArr = arr.filter((value, index) => {
    // return value >= 20;
//    return value % 2 === 0;
//});   //嘿嘿,用箭头函数也是一样哒~
console.log(newArr);

d. some()

  1. filter也是查找满足条件的元素,返回的是一个数组,把所有满足条件的元素返回

  2. some也是查找满足条件的元素是否存在,返回布尔值,找到就终止循环

array.some(function(currentValue, index, arr))
  • 返回值是布尔值,如果查找到这个元素,就返回true,如果查找不到就返回false
  • 如果找到第一个满足条件的元素,就终止循环,不再进行查找
 var arr = [10, 30, 4];
 var flag = arr.some(function(value) {
     // return value >= 20;  // true
     return value < 3;       // false
 });
 console.log(flag);

e. every()

every 方法是需要每一个返回值为 true,才能返回 true,否则为 false;

forEach和some区别
var arr = ['red', 'green', 'blue', 'pink'];
// 1. forEach迭代 遍历
// arr.forEach(function(value) {
//     if (value == 'green') {
//         console.log('找到了该元素');
//         return true; // 在forEach 里面 return 不会终止迭代
//filter()也不会终止迭代
//     }
//     console.log(11);
// })
// 如果查询数组中唯一的元素, 用some方法更合适,
arr.some(function(value) {
    if (value == 'green') {
        console.log('找到了该元素');
        return true; //  **在some 里面 遇到 return true 就是终止遍历 迭代效率更高**
    }
    console.log(11);
});

3.3 字符串方法

a. trim()

trim() 方法会从一个字符串的两端删除空白字符

str.trim();
  • trim() 方法并不影响字符串本身,它返回的是一个新的字符串

c. Object.keys()

用于获取对象自身所有的属性

var obj = {
    id: 1,
    pname: '小米',
    price: 1999,
    num: 2000
};
var arr = Object.keys(obj);
console.log(arr);
arr.forEach(function(value) {
    console.log(value);
})

c. Object.defineProperty()

定义新属性或修改原有的属性

Object.defineProperty(obj, prop, descriptor)

Object.defineProperty() 第三个参数: 以对象形式{}书写

  • value:设置属性的值 默认为undefined
  • writable:值是否可以重写,true/false 默认false
  • enumerable:目标属性是否可以被枚举。true|false 默认false
  • configuratble:目标属性是否可以被删除或是否可以再次修改特性true|false 默认为false
// 有就修改,没有就添加
Object.defineProperty(obj, 'num', {
    value: 1000,
    enumerable: true  // 能遍历
});
console.log(obj);
Object.defineProperty(obj, 'price', {
    value: 9.9
});
console.log(obj);
Object.defineProperty(obj, 'id', {
    // 如果值为false 不允许修改这个id属性值 默认值也是false
    writable: false,
});
Object.defineProperty(obj, 'address', {
    value: '中国山东蓝翔技校xx单元',
    // 如果只为false 不允许修改这个属性值 默认值也是false
    writable: false,
    // enumerable 如果值为false 则不允许遍历, 默认的值是 false
    enumerable: false,
    // configurable 如果为false 则不允许删除这个属性 不允许在修改第三个参数里面的特性 默认为false
    configurable: false
});
console.log(obj);
console.log(Object.keys(obj));
delete obj.address;
console.log(obj);
delete obj.pname;
console.log(obj);
Object.defineProperty(obj, 'address', {
    value: '中国山东蓝翔技校xx单元',
    // 如果值为false 不允许修改这个属性值 默认值也是false
    writable: true,
    // enumerable 如果值为false 则不允许遍历, 默认的值是 false
    enumerable: true,
    // configurable 如果为false 则不允许删除这个属性 默认为false
    configurable: true
});
console.log(obj.address);

以上是关于面向对象编程的主要内容,如果未能解决你的问题,请参考以下文章

面向面试编程代码片段之GC

Scala的面向对象与函数编程

面向对象编程

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

Java面向对象

面向对象编程(OOP)