一、面向对象:以对象作为基本单元进行编程
OO -> Object Oriented 面向对象
OOA -> Object Oriented Analyse 面向对象分析
OOD -> Object Oriented Design 面向对象设计
OOP -> Object Oriented Programming 面向对象编程
- 类(构造函数): 是描述一组具体相同行为和特征的对象,这些对象的抽象就是类
- 对象:类的具体实例,是包含属性和方法的集合
- 面向对象的特征:封装、继承、多态、抽象
封装:外界对客体内部属性的所有访问只能通过提供的用户接口实现。对象是封装的最基本单位。 继承:继承性是子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。 多态:多态性是指相同的操作或函数、过程可作用于多种类型的对象上并获得不同的结果, 不同的对象,收到同一消息可以产生不同的结果,这种现象称为多态性。 抽象:抽象是指强调实体的本质、内在的属性, 在系统开发中,抽象指的是在决定如何实现对象之前的对象的意义和行为 - OOP的好处: 复用性、灵活性、扩展性
- 面向对象解决的问题:
- 创建多个对象时,需要写大量重复代码
- 创建的多个对象无法按类型分类(无法进行类型识别)
- 相同类型的不同对象的行为方法不能复用(重复创建)
(一)、工厂模式
缺点:
- 无法进行类型识别
- 重复创建方法
function factory(name,age,sex){ let obj = new Object() obj.name = name obj.age = age obj.sex = sex obj.say = function(){console.log('hi~')} } let res1 = factory('张三',25,'男') let res2 = factory('李四',20,'男') console.log(res1.constructor) // Object console.log(res2.constructor) // Object console.log(res1.say == res2.say) // false
(二)、构造函数(另类的工厂模式)
缺点:
- 重复创建方法
function Human(name,age,sex){ // this -> new 出来的实例对象 // let this = new Object() 工厂模式 this.name = name this.age = age this.sex = sex this.say = function(){console.log('hi~')} // return this 工厂模式 } let res1 = new Human('张三',25,'男') let res2 = new Human('李四',20,'男') console.log(res1.constructor) // Human console.log(res2.constructor) // Human console.log(res1.say == res2.say) // false
(三)、原型模式
缺点:
- 所有的对象共享特征
function Human(){ Human.prototype.name = '张三' Human.prototype.age = '25' Human.prototype.sex = '男' Human.prototype.say = function(){console.log('hi~')} } let res1 = new Human() let res2 = new Human() console.log(res1.name) // 张三 console.log(res2.name) // 张三 console.log(res1.constructor) // Human console.log(res2.constructor) // Human console.log(res1.say == res2.say) // true
(四)、混合模式
```
//构造函数
function Human(name,age,sex){
this.name = name
this.age = age
this.sex = sex
}
//在原型对象上添加方法
Human.prototype.say = function(){console.log('hi~')}
let res1 = new Human('张三',25,'男')
let res2 = new Human('李四',20,'男')
console.log(res1.name) // 张三
console.log(res2.name) // 李四
console.log(res1.constructor) // Human
console.log(res2.constructor) // Human
console.log(res1.say == res2.say) // true
```
- 面向对象的目标 : 对一个对象进行编程
- 面向对象的
变量与属性:在同一作用域中使用变量,不同作用域中使用属性 - 构造函数的作用 : 提供一个对象供你编程
- 面向对象编程就是通过构造函数进行编程
(五)、示例
//模块化 形成独立作用域
(function(){
//1.创建构造函数
function Drag(obj){
//this -> 实例对象
this.dom = $(obj)
this.index = 1
this.addEvent() //调用函数
}
//2.添加事件
//在原型对象上添加属性,共享方法
Drag.prototype.addEvent = function(){
//this -> 实例对象
let _this = this //缓存this指向
this.dom.onclick=function(){
//this -> 添加事件的元素(this.dom)
_this.index //1
}
}
//3.拆分组合
function $(obj) return document.querySelector(obj)
//4.工厂模式
function factory(obj){
return new Drag(obj) //返回实例对象
}
//5.对外暴露
window.drag = factory //给window添加属性
})()
//调用函数
drag('.box')
二、构造函数
(一)、运算符
-
in运算符:判断属性是否在整个原型链中,返回布尔值
attr in objlet obj={name:'张三'} Object.prototype.hehe = '呵呵' console.log('hehe' in obj) //true //obj.hasOwnProperty(attr) 判断obj对象自身是否包含attr属性,返回布尔值 console.log(obj.hasOwnProperty('hehe')) //false -
instanceof运算符:判断一个 对象 的整个原型链中是否包含某个构造函数的prototype
let obj = {name:'张三'} let num = 1 //基本数据类型 let str = new String() //对象包装 console.log( obj instanceof Object );// true console.log( num instanceof Object );// false console.log( str instanceof Object );// true console.log( Object.prototype instanceof Object );// false -
new运算符new运算符做了哪些工作?- 1.创建一个空对象 :
var obj = new Object() - 2.将
obj._proto_的this指向改为Test.prototypeobj._proto_ = Test.prototype - 3.将构造函数的内部this指向obj对象
Test.call(obj) //this -> 实例对象 - 4.Test执行后默认返回obj对象 :
return obj
- 1.创建一个空对象 :
function Test(name){
this.name=name
}
let res = new Test('张三') // Test {name: '张三'}
(二)、构造函数
-
返回值 :
new运算符一定返回一个object类型- 若
return为基本类型 : 执行return this - 若
return为引用类型 : 以return值为准function Test(){ return 666 return [1,2,3] } let res = new Test(); console.log(res) //Test{} console.log(res) //[1,2,3]
- 若
-
继承 : 一个对象共享另一个对象的属性方法
原理 : 在子类中调用父类构造函数,并改变父类中的this指向
//父类 function Cat(name,color){ //this -> Cat this.name = name this.color = color } Cat.prototype.skill = function(){console.log('抓老鼠')} //子类 function Dog(food,name,color){ this.food = food Cat.call(this,name,color) // this -> Dog }
1.构造函数继承
let res = new Dog('water','耶耶','white')
res.skill() //报错
console.log(res)//Dog {food: 'water', name: '耶耶', color: 'white'}
/*原型链
res -> res._proto_ -> Dog.prototype -> Dog.prototype._proto_
-> Object.prototype
*/
2.原型继承 : 修改原型链
-
Dog.prototype = Cat.prototypeDog.prototype = Cat.prototype res.skill() //抓老鼠 /*原型链 res -> res._proto_ -> Dog.prototype -> Cat.prototype -> Cat.prototype._proto_ -> Object.prototype */ -
Dog.prototype = new Cat()Dog.prototype = new Cat() //实例对象 res.skill() //抓老鼠 /*原型链 res -> res._proto_ -> Dog.prototype -> Cat实例对象 -> Cat实例对象._proto_ -> Cat.prototype -> Cat.prototype._proto_ -> Object.prototype */ -
Dog.prototype = Object.create(Cat.prototype)Dog.prototype = Object.create( Cat.prototype ) //obj res.skill() //抓老鼠 /*原型链 res -> res._proto_ -> Dog.prototype -> obj -> obj._proto_ -> Cat.prototype -> Cat.prototype._proto_ -> Object.prototype */Object.create(obj/null)创建一个空对象,并指定该对象的原型对象
let test = { name: '呵呵' }; let res = Object.create(test); let res1 = Object.create(null); let res2 = {}; console.log(res); // {} test.prototype console.log(res1); // {} 无 prototype 属性 console.log(res2); // {} Object.prototype
3.混合继承
function Dog(food,name,color){
this.food = food
Cat.call(this,name,color) // this -> Dog
}//构造函数继承
Dog.prototype = Object.create(Cat.prototype)//原型继承
let res = new Dog('water','耶耶','white')
console.log(res)//Dog {food: 'water', name: '耶耶', color: 'white'}
res.skill() //抓老鼠
//构造器
console.log(Dog.prototype.constructor);//fn Cat()
4.指正实例的构造器(分类)
Dog.prototype.constructor = Dog
console.log(Dog.prototype.constructor);//fn Dog()