-
面向对象
概述
面向对象是一种变成思维(oop),主要是将对应的内容当作对象(万物皆对象)抽取里面的属性(名词)和方法(动词)。面向对象是利用万物皆对象的特点,将所有的内容都当作对象(object是所有对象的父类),进行构建。
面向对象的三大特点
- 封装(抽取其名词为属性 动词为方法)
- 继承(子类继承父类的非私有内容)
- 多态(重写(子类重写父类的方法) 和 重载(一个类中又两个同名的方法(JavaScript中不存在)))
面向对象与面向过程
面向过程(关注过程实现)
例如:餐馆吃饭 打车去餐馆——服务员点餐——厨师制作——上餐——吃饭——结账
面向对象(关注对象本身)
例如:餐馆吃饭 找餐馆这个对象(点餐)—— 自己这个对象(吃饭 结账)
面向对象的核心
找专业的人做专业的事(找有这个方法的对象去调用这个方法)
对象的构建
构造函数(使用new关键词)
普通构造函数(es5)
// 无参构造
function Person(){
}
var person = new Person()
//有参构造
function Person(name){
this.name=name//this 指向其构造的实例对象
}
var person = new Person('jack')
类的构造函数(es6)
// 类构造函数
class Person{
// 构造器 无参函数 被省略
constructor(){
}
}
var person = new Person()
console.log(person)
// 有参
class Person{
// 构造器 有参构造
constructor(name){
this.name=name//this指向当前构造的示例对象
}
}
var person = new Person('jack')
console.log(person)
class与构造函数的区别(面试题)
- 构造函数会进行预编译 class不会
- 构造函数可以当作普通函数使用 class必须使用new关键词调用
- class 默认采用严格模式 不允许重复命名
- class的extend可以继承静态内容 构造函数不行
- class中的方法都是不可枚举的(for in 不出来)
new关键词做了什么操作(面试题)
- 自动构造对象(将当前的构造对象的原型指向其构造函数的原型)
- 自动执行方法(手动设置属性)
- 自动返回对象
工厂函数(调用工厂方法)
function factory(name){
//手动创建对象
var obj={}
// 手动设置属性
obj.name=name
// 手动返回对象
return obj
}
// 调用工厂函数
var person = factory('旺财')
console.log(person)
工厂函数的特点
- 快速生产对象
- 忽略特点(差异化)
- 普通函数调用
运行流程
- 手动创建对象
- 手动设置属性
- 手动返回对象
封装
抽取对应的属性和方法封装为对象,属性为名词,方法为动词
示例
class Dog{
constructor(color,name){
this.color = color
this.name = name
}
run(){
console.log(`${this.color}的${this.name}在路上跑`)
}
}
var dog = new Dog('黄色','旺财')
dog.run() //黄色的旺财在路上跑
继承
- 继承主要是子类继承父类的非私有内容,class使用extend来实现继承
- class的extends关键词只能用于class的继承
- 它可以继承父类的所有非私有属性及方法(包括静态属性及方法)
示例
//class的extends关键词可以继承静态属性
//静态属性使用static关键词声明
class Person {
constructor(age) {
this.name = 'jack'
this.age = age
}
sayHello() {
console.log('你好')
}
static run(){
console.log('跑')
}
}
//静态属性的调用 静态属性使用类名调用
Person.run()
//使用extends来实现class的继承
class Son extends Person { //Son继承Person类
constructor(age, sex) {
//如果想使用this
super(age) //调用super指向对应的父类构造函数
this.sex = sex
}
}
var son = new Son(18, '男')
console.log(son) //{name:'jack',age:18,sex:'男'} 继承了父类的name属性及age属性
son.sayHello() //继承了父类的sayHello方法
//类名调用 继承的静态属性
Son.run()
多态
一个对象的多种形态的体现,主要存在两个内容,重写和重载
重载(同名不同参)
JavaScript没有重载
重载的区别
-
通过参数个数区分
-
通过参数类型区分
//第一个hello方法会被第二个覆盖 无法声明同名函数 出现同名函数必覆盖 function hello(arg){ console.log(arg) } hello(1) // 1 undefined function hello(arg1,arg2){ console.log(arg1,arg2) } hello(1,2) // 1 2
重写(子类重写父类)
必须基于继承关系
示例
class Animal{
constructor(){
}
run(){
console.log('某只动物在跑')
}
}
class Dog extends Animal{
constructor(name){
super()
this.name = name
}
run(){ //重写父类的方法
console.log(`${this.name}在跑`)
}
}
new Dog('旺财').run()
重写的好处
- 规范代码
- 新增提示
- 复用代码增加其多样性