初识面向对象

262 阅读7分钟

这是我参与8月更文挑战的第13天,活动详情查看:8月更文挑战

前言

相信大家都听过一句话啊,万物皆对象

人 , 车 ,猫

人 : 眼睛 头发 会敲代码 
车 : 品牌 价格 
猫 : 颜色 会抓老鼠 

以上都是数据 都记录在对象中 

var person = { 眼睛 ,头发 ,会敲代码 }

那到底什么是对象呢?我们先来简单的回顾一哈。

对象的概念: 对象是一个包含相关数据和方法的集合(通常由一些变量函数组成,我们称之为对象里面的属性方法),把很多零散的东西,,封装成为一个整体。

例如小明,他有升高,体重,年龄,性别等等;他还会干嘛啊,会吃饭,跑步,睡觉。那换成对象怎么表示呢?我们可以这样写

var person = {
  // 属性
  height: '180cm',
  weight: '70kg',
  age: 18,
  sex: 'man',

  // 行为
  eat: function () {
    console.log('小明会吃饭!');
  },
  run: function () {
    console.log('小明会跑步!');
  },
  sleep: function () {
    console.log('小明会睡觉!');
  }
}

那我们怎么样才能访问对象的属性和方法呢? 两种方法:

  • 点表示法
person.age  // 18
  • 括号表示法(是中括号[])
person['age']  // 18

括号表示法一个有用的地方是它不仅可以动态的去设置对象成员的值,还可以动态的去设置成员的名字

比如说,我们想让用户能够在他们的数据里存储自己定义的值类型,通过两个input框来输入成员的名字和值,通过以下代码获取用户输入的值:

var myDataName = nameInput.value
var myDataValue = nameValue.value

我们可以这样把这个新的成员的名字和值加到person对象里:

person[myDataName] = myDataValue

为了测试这个功能,尝试在你的代码里添加以下几行,就在person对象的右花括号的下面:

var myDataName = 'height'
var myDataValue = '1.75m'
person[myDataName] = myDataValue

现在,保存并刷新,在输入框里输入以下代码:

person.height

这是使用点表示法无法做到的,点表示法只能接受字面量的成员的名字,不接受变量作为名字。

一、面向对象与面向过程

都是一种解决问题的思路(思想)

面向过程:在解决问题的时候,关注的是解决问题需要的一个接着一个的过程,比较直观的通过代码实现某个业务。(代码是比较清晰的

面向对象:在解决问题的时候,关注的是解决问题所需要的对象(面向对象本身是对面向过程的封装,代码难点是理解this)

问:面向对象编程最重要的什么?

答:找到对象, 确定对象属性和行为。

举个例子啊:就是你做好饭然后就洗碗,是不是先得做饭然后再干嘛干嘛是吧。这里我们贴图方便理解一点。

面向过程:

1.png

面向对象:

2.png

那我们可以发现啊,面向过程就是有个先后顺序,一步接着一步。而面向对象呢,是把某一部分集中到一个对象中,然后再把属于当前版块的在一起进行操作。

那我们总结一下,面向对象的好处是什么?

  1. 更方便
  2. 复用性会更好
  3. 高内聚和低耦合
  4. 冗余(重复的东西)-->封装(提取相同的部分作为函数体,抽取不同的部分作为参数)

以及面向对象的三大特点

  1. 封装 : 对整体业务进行客观的描述 ,然后把相关数据记录在对象当中
  2. 继承 : 一个对象可以有子类,子类可继承父类的属性和方法
  3. 多态 : 对象可以有多个功能,多个方法, 一个方法可以有多种表现形式

二、面向对象-创建对象的方式

1. 字面量的方式创建对象

使用字面量的方式来创建对象差不多,都存在以下问题:

  1. 创建的对象无法复用,复用性差
  2. 如果需要创建多个同类型的对象,如(书籍)则需要写大量重复的代码,代码的冗余度高
var person = {
  // 属性
  height: '180cm',
  weight: '70kg',
  age: 18,
  sex: 'man',

  // 行为
  eat: function () {
    console.log('小明会吃饭!');
  },
  run: function () {
    console.log('小明会跑步!');
  },
  sleep: function () {
    console.log('小明会睡觉!');
  }
}

2. 内置构造函数的方式来创建对象

使用内置构造函数的方式来创建对象差不多,都存在以下问题:

  1. 创建的对象无法复用,复用性差
  2. 如果需要创建多个同类型的对象,如(书籍)则需要写大量重复的代码,代码的冗余度高

其实啊,就是使用 new Object

说到这又想起了一个经典面试题:new 关键字做了什么?。相信大家都不陌生。

//例如: 创建一个人对象
let person = new Object();

//person对象身上的属性
person.uname = '张三';

//person对象身上方法
person.eat = function () {
  console.log('我叫张三,我会吃饭。');
}

3. 简单工厂函数的方式来创建对象

我们可以这样简单的理解一下:

简单工厂模式:工厂里面有一些产品的模板, 只需要, 给工厂提供原材料; 工厂按照固定的加工方式, 就可以返回给外界同一类型的产品

那么所存在的问题是什么呢?

答:使用工厂方法创建的对象,使用构造函数都是object,所以创建的对象都是object这个类型,导致无法判定类型

function creatPerson(name, age, sex) {
  // 创建一个新的对象
  var obj = new Object();
  // 向对象里添加属性
  obj.name = name;
  obj.age = age;
  obj.sex = sex;
  obj.say = function () {
    console.log(this.name);
  };
  // 将新的对象返回
  return obj;
}
var person1 = creatPerson('Jack', 19, 'man');
var person2 = creatPerson('Rose', 29, 'female');
var person3 = creatPerson('Tom', 13, 'man');

4. 自定义构造函数的方式来创建对象

我们先简单写个代码,然后再分析分析构造函数和工厂函数的区别,构造函数的执行过程以及它的返回值

function Person(name, age) {
  // 隐式操作:把new新创建出来的对象赋值给this
  this.name = name;
  this.age = age;
  this.sayHello = function () {
    console.log("Hello World");
  }
}

var p = new Person('Jack', 20); //new Object(); 如果构造函数没有参数那么小括号是可以省略。
console.log('p ==> ', p);
p.sayHello();

4.1-自定义构造函数和简单工厂函数的对比

  • ① 函数的首字母大写(用于区别构造函数和普通函数)
  • ② 创建对象的过程是由new关键字实现
  • ③ 在构造函数内部会自动的创建新对象,并赋值给this指针
  • 自动返回(return)创建出来的对象 其实啊,这4个步骤就是new 关键字所做的事情。

4.2-构造函数的执行过程

  • ① 使用new关键字创建对象 ---- 外界
  • ② 把新创建出来的对象赋值给this
  • ③ 在构造函数内部,使用this为新创建出来的对象设置属性方法
  • ④ 默认返回新创建的对象(普通函数如果不显示的return则默认返回undefined)。

4.3-构造函数的返回值说明

  • 01 如果在构造函数中没有显示的return,则默认返回的是新创建出来的对象

  • 02 如果在构造函数中显示的return,则依照具体的情况处理

    • [01] return 的是对象,则直接返回该对象,取而代之本该默认返回的新对象
    • [02] return 的是null或基本数据类型值,则返回新创建的对象

总结:类型匹配才接受 --> 对象

三、面向对象-小案例(实现简易计算器)

  • 计算器加减乘除运算
  • 面向过程
  • 使用对象形式
  • 链式调用

1. 面向过程

就平常的操作,定义方法,调用方法。

<script>
    // 定义加减乘除4个方法

    function add(a, b) {
        return a + b;
    }

    function reduce(a, b) {
        return a - b;
    }

    function multiply(a, b) {
        return a * b;
    }

    function divide(a, b) {
        return a / b;
    }

    // (6 + 6) * 2 / 3 - 4
    console.log(reduce(divide(multiply(add(6, 6), 2), 3), 4), '11111');

</script>

2. 使用对象形式

<script>
    var Caculator = {
        // 结果
        result: 0,
        // 行为
        add: function (num) {
            this.result += num;
        },
        reduce: function(num) {
            this.result -= num;
        },
        multiply: function (num) {
            this.result *= num;
        },
        divide: function (num) {
            this.result /= num;
        },
        log: function () {
            console.log(this.result,, '2222')
        }
    };
    // (6 + 6) * 2 / 3 - 4
    Caculator.add(6);
    Caculator.add(6);
    Caculator.multiply(2);
    Caculator.divide(3);
    Caculator.reduce(4);
    Caculator.log();
</script>

3. 链式调用

<script>
    var Caculator = {
        // 结果
        result: 0,
        // 行为
        add: function (num) {
            this.result += num;
            return this;
        },
        reduce: function(num) {
            this.result -= num;
            return this;
        },
        multiply: function (num) {
            this.result *= num;
            return this;
        },
        divide: function (num) {
            this.result /= num;
            return this;
        },
        log: function () {
            console.log(this.result, '3333');
            return this;
        },
        clean: function () {
            this.result = 0;
            return this;
        }
    };

    // (6 + 6) * 2 / 3 - 4
    Caculator.add(6).add(6).multiply(2).divide(3).reduce(4).log(); // 4
    Caculator.clean().add(2).log(); // 2
</script>

四、结语

码字不易,如果觉得对你有帮助,觉得还不错的话,欢迎点赞收藏~

当然由于是个人整理,难免会出现纰漏,欢迎留言反馈。