面向对象编程

面向对象编程

一、面向对象编程思想

面向对象介绍

  1. 什么是对象,我们可以从两层来理解

    Everything is object (万物皆对象)

    1. 对象是单个事物的抽象,是一个具体的事物

      一本书、一辆汽车、一个人都可以是对象,一个数据库、一张网页、一个与远程服务器的连接也可以是对象。当实物被抽象成对象,实物之间的关系就变成了对象之间的关系,从而就可以模拟现实情况,针对对象进行编程

    2. 对象是一个容器,封装了属性(property)和方法(method)。

      属性是对象的状态特征,方法是对象的行为(完成某种任务)。比如,我们可以把动物抽象为animal对象,使用“属性”记录具体是那一种动物,使用“方法”表示动物的某种行为(奔跑、捕猎、休息等等)。

      在实际开发中,对象是一个抽象的概念,可以将其简单理解为:数据集或功能集。

      ECMAScript-262 把对象定义为:无序属性的集合,其属性可以包含基本值、对象或者函数。

      严格来讲,这就相当于说对象是一组没有特定顺序的值。对象的每个属性或方法都有一个名字,而每个名字都映射到一个值。

什么是面向对象编程

面向对象不是新的东西,它只是过程式代码的一种高度封装,目的在于提高代码的开发效率和可维护性。

面向对象编程 —— Object Oriented Programming,简称 OOP ,是一种编程开发思想。

它将真实世界各种复杂的关系,抽象为一个个对象,然后由对象之间的分工与合作,完成对真实世界的模拟。

在面向对象程序开发思想中,每一个对象都是功能中心,具有明确分工,可以完成接受信息、处理数据、发出信息等任务。

因此,面向对象编程具有灵活、代码可复用、高度模块化等特点,容易维护和开发,比起由一系列函数或指令组成的传统的过程式编程(procedural programming),更适合多人合作的大型软件项目。

面向对象的特征

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

编程思想:
面向过程:所有的事情都是亲力亲为,注重的是过程
面向对象:提出需求,找对象,对象解决,注重的是结果

js不是一门面向对象的语言,是基于对象的语言,js来模拟面向对象

面向对象的特性:封装,继承,多态,(抽象性)

封装:就是包装,把一些重用的内容进行包装,在需要的时候,直接使用把一个值,存放在一个变量中,把一些重用的代码放在函数中,把好多相同功能的函数放在一个对象中,把好多功能的对象,放在一个文件中,把一些相同的内容放在一个对象中
继承:类与类之间的关系,js中没有类的概念,js中有构造函数的概念,是可以有继承的,是基于原型
多态:同一个行为,针对不同的对象,产生了不同的效果
  • 应用软件开发的实质

    • 用软件方式解决现实生活中遇到的问题,提高人们的生产效率,改善人们的生活方式
    • 电商软件,解决人们足不出户,购物的问题
    • IM即时通讯软件,解决相隔千里的人们,面对面及时沟通聊天的问题
  • 面向对象编程思想是人们解决问题过程中的一种思考方式

  • 面向过程编程

    • 解决问题的过程,按步骤进行,第一步做什么,第二部做什么,一步一步完成
  • 面向对象编程

    • 找具有解决问题功能的对象,调用其功能,完成任务。如果对象不存在,则创建对象
  • 举个栗子🌰

       //纯javascript代码实现,还是函数实现
        //1 .纯javascript代码实现
        const splitStrOne = () => {
            let s = 'html_javascript_css'; // [html,javascript,css]
            //分析: 遍历每一个字符,判断是否_,如果不是_,拼接成字符串存储入数组,
            let array = []
            let str = '';
            for (let i = 0; i < s.length; i++) {
                const item = s.charAt(i);
                if (item != '_') {
                    str = str + item; //str: h   str:ht   str:htm  str:html   str:html   str:css
                } else {
                    array.push(str); // [html]
                    str = '';
                }
                if (s.length - 1 == i) {
                    array.push(str); // [html]
                    str = '';
                }
            }
            console.log(array);
        }
    
        //2. 纯函数方式实现
        const splitStrTwo = () => {
            let s = 'html_javascript_css'; // [html,javascript,css]
            const array = s.split('_');
            console.log(array);
        }
        splitStrTwo();
        
        //面向以象编程思想: 找解决问题对象,如果对象存在,调用对象相关功能方法解决问题,如果对象不存在,自己封对象实现功能。
        //思考: 现实生活中对象   软件世界中对象
    
    
  • 面向对象与面向过程

    • 面向过程就是亲力亲为,事无巨细,面面俱到,步步紧跟,有条不理
    • 面向对象就是找一个对象,指挥得结果
    • 面向对象将执行者变成指挥者
    • 面向对象不是面向过程的替代,而是面向过程的封装

二、创建对象方式

  1. 简单方式new Object

    //简单方式创建对象
    let obj = new Object()
    obj.name = 'jack'
    obj.age = 13
    obj.playGame = function(){
        console.log('玩游戏')
    }
    obj.playGame()
    
  2. 字面量方式

    //字面量方式
    let obj = {
        name:'jack',
        age = 18,
        playGame:function(){
        console.log('玩游戏')
    }
    }
    obj.playGame()
    
  3. 工厂函数

    //简单方式的改进:工厂函数
    //我们可以写一个函数,解决代码重复的问题
    function createPerson(name,age){
        return{
            name:name,
            age:age,
                sayName:function(){
                    console.log(this.name)
                }
        }
    }
    //然后生成实例对象
    var p1 = createPerson('jack',18)
    var p2 = createPerson('Mike',18)
    

三、构造函数

1.更优雅的工厂函数-构造函数

function Person(name,age){
    this.name = name
    this.age = age
    this.sayName = function(){
        console.log(this.name)
    }
}
var p1 = new Person('jack',18)
p1.sayName()	//jack
var p2 = new Person('Mike',23)
p2.sayName()	//Mike

2.解析构造函数代码的执行

在上面的示例中,Person() 函数取代了 createPerson() 函数,但是实现效果是一样的。

这是为什么呢?

我们注意到,Person() 中的代码与 createPerson() 有以下几点不同之处:

  • 没有显示的创建对象
  • 直接将属性和方法赋给了this 对象
  • 没有 return 语句
  • 函数名使用的是大写的Person

而要创建Person 实例,则必须使用new 操作符。
以这种方式调用构造函数会经历以下4 个步骤:

  1. 创建一个新对象

  2. 将构造函数的作用域赋给新对象(因此this 就指向了这个新对象)

  3. 执行构造函数中的代码

  4. 返回新对象

    function Person(name,age){
        //当使用new操作符调用Person()的时候,实际上这里会先创建一个对象
        //var instance = {}
        //this = instance
        //接下来所有针对this的操作实际上操作的就是instance
        this.name = name
        this.age = age
        this.sayName = function(){
            console.log(this.name)
        }
        //在函数的结尾会将this返回,也就是instance
        //return this
    }
    

3.构造函数示例

//构造函数-对象模板 this表示当前对象
function Person(name,age,sex){
    this.name = name
    this.age = age
    this.sex = sex
    this.readBook = function(){
        console.log(this.name,'读书')
    }
}
//创建对象,实例化对象
let p1 = new Person('jack',10,'女')
p1.readBook()
let p2 = new Person('mike',10,'男')
p2.readBook()

四、检查对象类型

instanceof

let arr = []
console.log(arr instanceof Array)	//true
console.log(arr instanceof Date)	//false

五、原型prototype

构造函数、实例、引用变量、对象名,对象概念区分

使用 prototype 原型对象解决构造函数的问题。

每创建一个对象都会在内存中分配存储空间,对于对象公共的方法,能不能只创建一份?

  • Javascript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象(原型对象prototype)
  • 这个原型对象的所有属性和方法,都会被构造函数的实例访问(继承)。
  • 这也就意味着,我们可以把所有对象实例需要共享的属性和方法直接定义在 prototype 对象上。
    function Person (name, age) {
      this.name = name
      this.age = age
    }
    console.log(Person.prototype)
    Person.prototype.type = 'human'
    Person.prototype.sayName = function () {
      console.log(this.name)
    }
    var p1 = new Person(...)
    var p2 = new Person(...)
    console.log(p1.sayName === p2.sayName)	//true
	//这时所有实例的 type 属性和 sayName() 方法,
	//其实都是同一个内存地址,指向 prototype 对象,因此就提高了运行效率。
  • 构造函数、实例、原型三者之间的关系

在这里插入图片描述

属性成员的搜索原则 - 原型链
了解了 构造函数-实例-原型对象 三者之间的关系后,接下来我们来解释一下为什么实例对象可以访问原型对象中的成员。

每当代码读取某个对象的某个属性时,都会执行一次搜索,目标是具有给定名字的属性

  • 搜索首先从对象实例本身开始
  • 如果在实例中找到了具有给定名字的属性,则返回该属性的值
  • 如果没有找到,则继续搜索指针指向的原型对象,在原型对象中查找具有给定名字的属性
  • 如果在原型对象中找到了这个属性,则返回该属性的值

也就是说,在我们调用 person1.sayName() 的时候,会先后执行两次搜索:

  • 首先,解析器会问:“实例 person1 有 sayName 属性吗?”答:“没有。
  • ”然后,它继续搜索,再问:“ person1 的原型有 sayName 属性吗?”答:“有。
  • ”于是,它就读取那个保存在原型对象中的函数。
  • 当我们调用 person2.sayName() 时,将会重现相同的搜索过程,得到相同的结果。

而这正是多个对象实例共享原型所保存的属性和方法的基本原理。

总结:

  • 先在自己身上找,找到即返回
  • 自己身上找不到,则沿着原型链向上查找,找到即返回
  • 如果一直到原型链的末端还没有找到,则返回 undefined

原型链

当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值