JavaScript 面向对象编程基础 && 显式原型

什么是面向对象?

  • 面向对象 英文Object Oriented,缩写OO

  • 面向对象是一种软件开发方法,它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的灵活性、重用性和扩展性。

  • 面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物,是一种高级的编程思想。

  • 面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统、交互式界面、应用结构、应用平台、分布式系统、网络管理结构、CAD技术、人工智能等领域。

  • 面向对象的特征:封装、继承、抽象、多态

  1. 封装:
    封装是指将现实世界中存在的某个客体的属性与行为绑定在一起,并放置在一个逻辑单元内。该逻辑单元负责将所描述的属性隐藏起来,外界对客体内部属性的所有访问只能通过提供的用户接口实现。对象是封装的最基本单位。

  2. 继承:
    继承性是子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并加入若干新的内容。

  3. 抽象:
    抽象是指强调实体的本质、内在的属性。在系统开发中,抽象指的是在决定如何实现对象之前的对象的意义和行为。使用抽象可以尽可能避免过早考虑一些细节。

  4. 多态:
    多态性是指相同的操作或函数、过程可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息可以产生不同的结果,这种现象称为多态性。

  • 面向对象分析-OOA(Object-Oriented Analysis),是确定需求或者业务的角度,按照面向对象的思想来分析业务。

  • 面向对象设计-OOD(Object-Oriented Design),是OO方法中一个中间过渡环节。其主要作用是对OOA分析的结果作进一步的规范化整理,管理程序内部各部分的相互依赖。

  • 面向对象编程-OOP(Object-Oriented Programming),是以建立模型体现出来的抽象思维过程和面向对象的方法。OOP的主要目标:重用性、灵活性和扩展性,核心概念是类和对象
    JS中讲的类->构造函数 方法->函数

  • 面向过程是一种直接的编程方法,它是按照编程的思路考虑问题,通过顺序执行一组语句来实现一个功能。

  1. 面向过程 ==> 从细节方面考虑问题
  2. 面向对象 ==> 从宏观方面考虑问题
  3. 面向过程 ==> 类似于’自己造电脑’
  4. 面向对象 ==> 类似于’自己组装电脑’

类与对象

  • 类描述了一组有相同特性和相同行为的对象,具有相同属性和相同方法的对象的抽象就是类

  • 对象把数据及对数据的操作方法放在一起作为一个整体,对象是带有属性和方法的集合

  • 对象的抽象是类

  • 类的实例是对象

  • 类与对象的关系:模板 -> 产品

  • “JavaScript中所有事物都是对象”,如 字符串、数组、函数…等等

  • 因为所有事物均继承自Object,都是Object的实例

  1. 变量和属性:
  • 变量是自由的,属性是属于对象的,是与对象相关的值
  1. 函数和方法:
  • 函数是自由的,方法是属于对象的,是与对象相关的函数

创建对象

在JavaScript中创建对象有多种不同的方法:

  1. Object构造函数
  2. 对象字面量
  3. 工厂模式
  4. 构造函数
  5. 原型模式
  6. 混合模式

Object构造函数

var obj1 = new Object()
obj1.name = 'xiaocuo'
obj1.age = 25
obj1.sayHi = function (){
    alert('hi,大家好!我叫' + obj1.name)
}
// 或者:
var obj2 = {}
obj2.name = 'laowang'
obj2.age = 35
obj2.sayHi = function (){
    alert('hi,大家好!我叫' + obj2.name)
}

对象字面量

var obj3 = {
    name: 'laozhao'
    age: 23,
    sayHi: function (){
        alert('hi,大家好!我叫' + obj3.name)
    }
}

以上方式的缺陷:创建多个对象时,会产生大量的重复代码

工厂模式

  • 原料 => 加工 => 出厂
function createObj( n, a ){
    // 原料
    var obj = {}

    // 加工
    obj.name = n
    obj.age = a
    obj.sayHi = function (){
        alert('hi,大家好!我叫' + obj.name)
    }

    // 出厂
    return obj
}
var obj1 = createObj('小王', 23)
var obj2 = createObj('小李', 24)
console.log( obj1.constructor ) // Object
console.log( obj1.sayHi === obj2.sayHi ) // false

对象的 constructor 属性,指向对象的构造器(类)

  • 工厂模式的缺陷:
  1. 工厂模式创建对象时,没办法解决对象类型识别的问题
  2. 工厂模式创建多个对象时,不同对象的相同方法仍然存在多个,既不环保,又不高效

构造函数

  • 当任意一个普通函数用于创建一类对象,并通过new操作符来调用时,它就是一个构造函数

  • 作用:构造新对象(设置对象的属性和方法)

  • ECMAScript提供了多个原生对象,如 Object、Array、String、Number、Date…等

  • 此外,ECMAScript允许自定义构造函数

构造函数的实现:

  1. 按照惯例,构造函数通常以一个大写字母开头,在js中看到大写字母开头的函数都是构造函数!!
  2. 在函数内部给 this 添加属性和方法,因为this就表示当前运行时的对象
function Human( n, a ){ // 构造函数  类
    this.name = n
    this.age = a
    this.sayHi = function (){
        alert('hi,大家好!我叫' + this.name)
    }
}
var obj1 = new Human('张三', 18)
var obj2 = new Human('李四', 19)
  • 构造函数相当于JS内置的工厂模式
function Human( n, a ){ // 构造函数
    // var this = {} 使用new调用时自动完成
    this.name = n
    this.age = a
    this.sayHi = function (){
        alert('hi,大家好!我叫' + this.name)
    }
    // return this 使用new调用时自动完成
}
var obj1 = new Human('张三', 18)
var obj2 = new Human('李四', 19)
console.log( obj1.constructor ) // Human
console.log( obj1.sayHi === obj2.sayHi ) // false

面试题

  • new操作符做了什么?
    1. 创建一个空对象obj
      var obj = new Object()
    2. 将obj的__proto__属性指向构造函数的原型(将obj的隐式原型指向构造函数的显式原型)
      obj.proto = constructor.prototype
    3. 将构造函数内的this绑定到新建的对象obj,并执行构造函数(跟调用普通函数一样)
      constructor.call(obj)
    4. 若构造函数的返回值不是引用类型,则返回新建的对象(默认this),否则直接返回引用类型的值
      return this
      return ‘abc’
      return {a:1,b:2}

构造函数的缺陷:

解决了对象类型识别的问题,但是创建多个对象时,不同对象的相同方法仍然存在多个

原型(显式原型)

  • 每个函数对象都有一个prototype(原型)属性,这个属性指向一个对象,即原型对象
  • prototype原型是函数的一个默认属性,在函数的创建过程中由JS引擎自动添加
  • prototype的作用:所有添加到prototype的属性和方法都将被所有对象实例共享(继承)
Object.prototype.abc = '123'
var str = 'qwe'
var arr = [4,5,6]
var bool = true
var fun = function () {}
console.log(str.abc)
console.log(arr.abc)
console.log(bool.abc)
console.log(fun.abc)

function Cat(){ }
Cat.prototype.name = '小白'
Cat.prototype.color = 'white'
Cat.prototype.food = 'fish'
Cat.prototype.skill = function (){        
    alert('卖萌~喵喵喵~~~')
};
var cat1 = new Cat() //实例
var cat2 = new Cat() //实例
alert(cat1.skill === cat2.skill) //true    
alert(cat1.name === cat2.name) //true

原型模式的缺陷:

  1. 原型模式省略了为构造函数传递参数这一环节,结果所有实例都将取得相同的属性值
  2. prototype中的属性和方法共享,对于函数来说非常适合,但属性共享,问题可能很严重

在这里插入图片描述

混合模式

  • 混合使用构造函数和原型模式,是目前JS中使用最广泛、认同度最高的一种创建对象的方法
  • 构造函数用于定义实例属性,原型用于定义共享的属性和方法
  • 即可以共享方法,又可以向构造函数传递参数,集两种模式之长
function Person(n,s,a){
    this.name = n
    this.sex = s
    this.age = a
}
Person.prototype.attr = '人类'
Person.prototype.eat = function (){
    alert('什么都吃')
}
var p1 = new Person('老王','男',36)
var p2 = new Person('小宋','女',26)
console.log(p1.constructor) //Person
console.log(p1.eat === p2.eat) //true

小结

  • 面向对象 目标 => 对一个对象进行编程

  • 构造函数 作用 => 提供一个对象供你编程

  • 通过构造函数实现面向对象编程

    1. 定义构造函数,通常函数名的首字母大写 function Tab(){}

    2. 把变量变成对象的属性
      var prevIndex = 0
      this.prevIndex = 0

    3. 把函数变成对象的方法(prototype原型)

    4. 构造函数实例化

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值