面向对象编程
- 面向过程编程
解决问题的过程按步骤进行,第一步做什么,第二步做什么 - 面向对象编程
解决问题的话找能解决问题的我对象,让对象的方法解决问题,如果没有这个对象,就创建这个对象
创建对象方式
- 简单方式new obj
- 字面量方式
- 工厂函数
- 构造函数
- 函数名就是对象类型名(首字母大写)
- 构造函数中,通过this关键字定义属性和方法
- 通过new语句调用构造函数对象
<script>
//简单方式
let personpObj=new Object()
personpObj.name='jack';
personpObj.age=20
personpObj.playGame=function(){
console.log('打游戏');
}
personpObj.playGame()
//结果打游戏
//字面量方式
let person1={
name:'jack',
age:20,
playGame:function(){
console.log('打游戏')
}
}
person1.playGame()
//结果打游戏
//工厂函数
function person3(name,age){
return{
name,
age,
playGame:function(){
console.log(this.name+'打游戏');
}
}
}
let person3_1=person3('jack',20)
person3_1.playGame()
//结果jack打游戏
//构造函数
function Person4(name,age){
this.name=name;
this.age=age;
this.playGame=function(){
console.log(this.name+'打游戏');
}
}
let person4_1=new Person4('jack',20)
person4_1.playGame()
//结果jack打游戏
构造函数特点
- 构造函数也是函数,任何函数只要使用new操作符调用就是构造函数。而不使用new操作符调用的函数就是普通函数
function Person(name){
this.name=name
this.say=function(){
console.log(this.name,'说话');
}
}
let person1=new Person('rose')
person1.say()
//结果rose说话
Person('rose')
window.say()
//结果rose说话
注:如果函数没有用new操作符,那么属性和方法会自动添加到window对象上
2. 构造函数的问题
构造函数定义的问题会在每个实例上都创建一遍,也就是
this.say=new function('console.log(this.name)')
要解决这个问题可以把函数定义到构造函数外部,但这样会导致全局作用域被搞乱,这里的函数只是一个指向外部的指针
<script>
function Person(name){
this.name=name
this.say=say
}
//这里在函数体外部
function say(){
console.log(this.name,'说话');
}
let person1=new Person('jack')
person1.say()
//结果jack说话
</script>
检查对象类型
instanceof关键字判定数据类型对象
方法:对象 instanceof 数据类型
<script>
let arr=[1,2]
console.log(arr instanceof Array);
//结果true
function Person(name){
this.name=name
this.say=say
}
function say(){
console.log(this.name,'说话');
}
function Substance(name) {
this.name=name
}
let person1=new Person('jack')
console.log(person1 instanceof Person);
//结果true
console.log(person1 instanceof Substance );
//结果false
</script>
原型对象
- 实例对象的公共属性和方法,提取出来定义到一个独立的对象,节约内存空间
- JS规定,每个构造函数都有一个prototype指向它的原型
- 在原型对象上定义的属性和方法可以被所有构造函数实例对象访问
注:为何实例对象能访问原型对象的公共属性和方法?
每个对象都有一个隐藏原型对象__proto__指向原型对象
对象查找时,先查找构造函数中方法,没有再查找原型对象中的方法
实例:做个选项卡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
.wrap{
width: 300px;
height: 200px;
margin: 10px auto;
}
ul{
width: 300px;
height: 40px;
}
ul li{
width: 100px;
height: 40px;
float: left;
background-color: skyblue;
list-style: none;
text-align: center;
line-height: 40px;
}
.active{
background-color: red;
}
.content{
width: 300px;
height: 160px;
background-color: pink;
}
ol{
width: 300px;
height: 160px;
}
ol li{
width: 300px;
height: 160px;
list-style: none;
background-color: orange;
display: none;
}
.diplayBlock{
display: block;
}
</style>
</head>
<body>
<div class="wrap" id="tab1">
<ul>
<li class="active" date-index="1">选项1</li>
<li date-index="2">选项2</li>
<li date-index="3">选项3</li>
</ul>
<div class="content">
<ol>
<li>这是选项框1gsdfsdgf</li>
<li>这是选项框2</li>
<li>这是选项框3</li>
</ol>
</div>
</div>
<script>
function OnTab(id){
//通过传入参数设置根节点,避免选项卡多的时候混淆
this.root=document.querySelector(id)
//拿到所有ul下li
this.lis=this.root.querySelectorAll('ul>li')
this.contentEle=this.root.querySelector('.content')
//拿到所有ol下li
this.ols=this.root.querySelectorAll('ol>li')
this.tab=function (){
//因为点击事件里this指向点击对象,所以外面构造函数的this需要定义才能使用
let _this=this
for(let i=0;i<this.lis.length;i++){
this.lis[i].οnclick=function(e){
target=e.target
//清除
_this.onClear()
//添加选中颜色是
_this.lis[i].classList.add('active')
//拿到索引号以确定ol下对应li
let index=target.getAttribute('date-index')
//对应li显示在页面
_this.ols[index-1].classList.add('diplayBlock')
}
}
}
this.onClear=function(){
for(let j=0;j<this.lis.length;j++){
//清除颜色
this.lis[j].classList.remove('active')
//清除Li显示
this.ols[j].classList.remove('diplayBlock')
}
}
}
//构造函数
let tab1=new OnTab('#tab1')
//调用方法
tab1.tab()
</script>
</body>
</html>