什么是面向对象?
-
面向对象 英文Object Oriented,缩写
OO
-
面向对象是一种软件开发方法,它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的灵活性、重用性和扩展性。
-
面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物,是一种高级的编程思想。
-
面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统、交互式界面、应用结构、应用平台、分布式系统、网络管理结构、CAD技术、人工智能等领域。
-
面向对象的特征:封装、继承、抽象、多态
-
封装:
封装是指将现实世界中存在的某个客体的属性与行为绑定在一起,并放置在一个逻辑单元内。该逻辑单元负责将所描述的属性隐藏起来,外界对客体内部属性的所有访问只能通过提供的用户接口实现。对象是封装的最基本单位。 -
继承:
继承性是子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并加入若干新的内容。 -
抽象:
抽象是指强调实体的本质、内在的属性。在系统开发中,抽象指的是在决定如何实现对象之前的对象的意义和行为。使用抽象可以尽可能避免过早考虑一些细节。 -
多态:
多态性是指相同的操作或函数、过程可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息可以产生不同的结果,这种现象称为多态性。
-
面向对象分析-
OOA
(Object-Oriented Analysis),是确定需求或者业务的角度,按照面向对象的思想来分析业务。 -
面向对象设计-
OOD
(Object-Oriented Design),是OO方法中一个中间过渡环节。其主要作用是对OOA分析的结果作进一步的规范化整理,管理程序内部各部分的相互依赖。 -
面向对象编程-
OOP
(Object-Oriented Programming),是以建立模型体现出来的抽象思维过程和面向对象的方法。OOP的主要目标:重用性、灵活性和扩展性,核心概念是类和对象
。
JS中讲的类->构造函数 方法->函数 -
面向过程是一种直接的编程方法,它是按照编程的思路考虑问题,通过顺序执行一组语句来实现一个功能。
- 面向过程 ==> 从细节方面考虑问题
- 面向对象 ==> 从宏观方面考虑问题
- 面向过程 ==> 类似于’自己造电脑’
- 面向对象 ==> 类似于’自己组装电脑’
类与对象
-
类描述了一组有相同特性和相同行为的对象,具有相同属性和相同方法的对象的抽象就是类
-
对象把数据及对数据的操作方法放在一起作为一个整体,对象是带有属性和方法的集合
-
对象的抽象是类
-
类的实例是对象
-
类与对象的关系:模板 -> 产品
-
“JavaScript中所有事物都是对象”,如 字符串、数组、函数…等等
-
因为所有事物均继承自Object,都是Object的实例
- 变量和属性:
- 变量是自由的,属性是属于对象的,是与对象相关的值
- 函数和方法:
- 函数是自由的,方法是属于对象的,是与对象相关的函数
创建对象
在JavaScript中创建对象有多种不同的方法:
- Object构造函数
- 对象字面量
- 工厂模式
- 构造函数
- 原型模式
- 混合模式
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 属性,指向对象的构造器(类)
- 工厂模式的缺陷:
- 工厂模式创建对象时,没办法解决对象类型识别的问题
- 工厂模式创建多个对象时,不同对象的相同方法仍然存在多个,既不环保,又不高效
构造函数
-
当任意一个普通函数用于创建一类对象,并通过new操作符来调用时,它就是一个构造函数
-
作用:构造新对象(设置对象的属性和方法)
-
ECMAScript提供了多个原生对象,如 Object、Array、String、Number、Date…等
-
此外,ECMAScript允许自定义构造函数
构造函数的实现:
- 按照惯例,构造函数通常以一个大写字母开头,在js中看到大写字母开头的函数都是构造函数!!
- 在函数内部给 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操作符做了什么?
- 创建一个空对象obj
var obj = new Object() - 将obj的__proto__属性指向构造函数的原型(将obj的隐式原型指向构造函数的显式原型)
obj.proto = constructor.prototype - 将构造函数内的this绑定到新建的对象obj,并执行构造函数(跟调用普通函数一样)
constructor.call(obj) - 若构造函数的返回值不是引用类型,则返回新建的对象(默认this),否则直接返回引用类型的值
return this
return ‘abc’
return {a:1,b:2}
- 创建一个空对象obj
构造函数的缺陷:
解决了对象类型识别的问题,但是创建多个对象时,不同对象的相同方法仍然存在多个
原型(显式原型)
- 每个函数对象都有一个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
原型模式的缺陷:
- 原型模式省略了为构造函数传递参数这一环节,结果所有实例都将取得相同的属性值
- 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
小结
-
面向对象 目标 => 对一个对象进行编程
-
构造函数 作用 => 提供一个对象供你编程
-
通过构造函数实现面向对象编程
-
定义构造函数,通常函数名的首字母大写 function Tab(){}
-
把变量变成对象的属性
var prevIndex = 0
this.prevIndex = 0 -
把函数变成对象的方法(prototype原型)
-
构造函数实例化
-