javascript面向对象基础(1)
主题
1)工厂模式
2)new运算符
3)构造函数
4)原型prototype
5)面相对象和面相过程编程
6)类和对象
## 知识点
##需求
### 1、需求一:实现多个选项卡的
- 问题一:如何写?按照以前方式写
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div class="mydiv1"> <button style="background: red">按钮一</button> <button>按钮二</button> <button>按钮三</button> <p style="display: block;">div1</p> <p style="display: none;">div2</p> <p style="display: none;">div3</p> </div> </body> <script> // 第一个需求 一个选项卡; let btns = document.querySelectorAll(".mydiv1 button"); let ps = document.querySelectorAll(".mydiv1 p"); btns.forEach((v,k)=>{ v.onclick = function(){ ps.forEach((value,key)=>{ if(key==k){ // 选中项; btns[key].style.background = "red"; ps[key].style.display = "block"; }else{ // 非选中项; btns[key].style.background = ""; ps[key].style.display = "none"; } }) } }) </script> </html>
- 问题二:如何提高复用性?(函数封装)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div class="mydiv1"> <button style="background: red">按钮一</button> <button>按钮二</button> <button>按钮三</button> <p style="display: block;">div1</p> <p style="display: none;">div2</p> <p style="display: none;">div3</p> </div> <div class="mydiv2"> <button style="background: red">按钮一</button> <button>按钮二</button> <button>按钮三</button> <p style="display: block;">div1</p> <p style="display: none;">div2</p> <p style="display: none;">div3</p> </div> </body> <script> // 第二个需求 多个选项卡; function Tab(btns, ps) { btns.forEach((v, k) => { v.onclick = function () { ps.forEach((value, key) => { if (key == k) { // 选中项; btns[key].style.background = "red"; ps[key].style.display = "block"; } else { // 非选中项; btns[key].style.background = ""; ps[key].style.display = "none"; } }) } }) } let btns = document.querySelectorAll(".mydiv1 button"); let ps = document.querySelectorAll(".mydiv1 p"); Tab(btns,ps); let btns2 = document.querySelectorAll(".mydiv2 button"); let ps2 = document.querySelectorAll(".mydiv2 p"); Tab(btns2,ps2); </script> </html>
###2、需求变更:其中某一个实现选项卡点击切换下一页功能
- 通过传统的传参数来解决 ;逻辑和判断越来越复杂;
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div class="mydiv1"> <button style="background: red">按钮一</button> <button>按钮二</button> <button>按钮三</button> <p style="display: block;">div1</p> <p style="display: none;">div2</p> <p style="display: none;">div3</p> </div> <div class="mydiv2"> <button style="background: red">按钮一</button> <button>按钮二</button> <button>按钮三</button> <p style="display: block;">div1</p> <p style="display: none;">div2</p> <p style="display: none;">div3</p> </div> <button class="nextPre">点击我第一个选项卡下一页切换</button> </body> <script> // 第三个需求 3-点击按钮第一个选项卡有下一页功能 function Tab(btns, ps, isNext = false) { btns.forEach((v, k) => { v.onclick = function () { psFor(k); } }) if (isNext) { // 有下一页功能; let num = 0; document.querySelector(".nextPre").onclick = function () { num++; num = num > 2 ? 0 : num psFor(num); } } function psFor(k) { ps.forEach((value, key) => { if (key == k) { // 选中项; btns[key].style.background = "red"; ps[key].style.display = "block"; } else { // 非选中项; btns[key].style.background = ""; ps[key].style.display = "none"; } }) } } let btns = document.querySelectorAll(".mydiv1 button"); let ps = document.querySelectorAll(".mydiv1 p"); Tab(btns, ps, true); let btns2 = document.querySelectorAll(".mydiv2 button"); let ps2 = document.querySelectorAll(".mydiv2 p"); Tab(btns2, ps2); </script> </html>
###3、需求变更:另一个实现轮播图功能
- 如何灵活的自动播放?—>需要返还函数还需要返还属性:可以通过返还对象来解决;
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div class="mydiv1"> <button style="background: red">按钮一</button> <button>按钮二</button> <button>按钮三</button> <p style="display: block;">div1</p> <p style="display: none;">div2</p> <p style="display: none;">div3</p> </div> <div class="mydiv2"> <button style="background: red">按钮一</button> <button>按钮二</button> <button>按钮三</button> <p style="display: block;">div1</p> <p style="display: none;">div2</p> <p style="display: none;">div3</p> </div> <button class="nextPre">点击我第一个选项卡下一页切换</button> <button class="autoPlay">点击按钮第二个选项卡有自动轮播功能</button> </body> <script> // 第四个需求 4-点击按钮第二个选项卡有自动轮播功能 function Tab(btns, ps, isNext = false, isAutoPlay = false) { btns.forEach((v, k) => { v.onclick = function () { psFor(k); } }) if (isNext) { // 有下一页功能; let num = 0; document.querySelector(".nextPre").onclick = function () { num++; num = num > 2 ? 0 : num psFor(num); } } if (isAutoPlay) { // 控制自动轮播 let num = 0; document.querySelector(".autoPlay").onclick = function () { setInterval(() => { num++; num = num > 2 ? 0 : num psFor(num); }, 1000); } } function psFor(k) { ps.forEach((value, key) => { if (key == k) { // 选中项; btns[key].style.background = "red"; ps[key].style.display = "block"; } else { // 非选中项; btns[key].style.background = ""; ps[key].style.display = "none"; } }) } } let btns = document.querySelectorAll(".mydiv1 button"); let ps = document.querySelectorAll(".mydiv1 p"); // 下一页功能 轮播功能; 某一个选项卡的需求; Tab(btns, ps, true); let btns2 = document.querySelectorAll(".mydiv2 button"); let ps2 = document.querySelectorAll(".mydiv2 p"); Tab(btns2, ps2, false, true); </script> </html>
###4、需求变更:多个选项卡分别更改数量
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div class="mydiv1"> <button style="background: red">按钮一</button> <button>按钮二</button> <button>按钮三</button> <p style="display: block;">div1</p> <p style="display: none;">div2</p> <p style="display: none;">div3</p> </div> <div class="mydiv2"> <button style="background: red">按钮一</button> <button>按钮二</button> <button>按钮三</button> <p style="display: block;">div1</p> <p style="display: none;">div2</p> <p style="display: none;">div3</p> </div> <button class="nextPre">点击我第一个选项卡下一页切换</button> <button class="autoPlay">点击按钮第二个选项卡有自动轮播功能</button> </body> <script> // 第四个需求 4-点击按钮第二个选项卡有自动轮播功能 function Tab(btns, ps) { btns.forEach((v, k) => { v.onclick = function () { psFor(k); } }) // if (isNext) { // // 有下一页功能; // let num = 0; // document.querySelector(".nextPre").onclick = function () { // num++; // num = num > 2 ? 0 : num // psFor(num); // } // } // if (isAutoPlay) { // // 控制自动轮播 // let num = 0; // document.querySelector(".autoPlay").onclick = function () { // setInterval(() => { // num++; // num = num > 2 ? 0 : num // psFor(num); // }, 1000); // } // } function psFor(k) { ps.forEach((value, key) => { if (key == k) { // 选中项; btns[key].style.background = "red"; ps[key].style.display = "block"; } else { // 非选中项; btns[key].style.background = ""; ps[key].style.display = "none"; } }) } return psFor; } let btns = document.querySelectorAll(".mydiv1 button"); let ps = document.querySelectorAll(".mydiv1 p"); // 下一页功能 轮播功能; 一个需求; let tab1 = Tab(btns, ps); // 下一页功能 let num = 0; document.querySelector(".nextPre").onclick = function () { num++; num = num > 2 ? 0 : num tab1(num); } let btns2 = document.querySelectorAll(".mydiv2 button"); let ps2 = document.querySelectorAll(".mydiv2 p"); let tab2 = Tab(btns2, ps2); // 自动轮播 let num2 = 0; document.querySelector(".autoPlay").onclick = function () { setInterval(() => { num2++; num2 = num2 > 2 ? 0 : num2 tab2(num2); }, 1000); } </script> </html>
## 工厂模式
一、工厂模式
工厂模式解决了代码复用的问题,
1.但是却没有解决对象识别的问题。即创建的所有实例都是Object类型。(不清楚是哪个对象的实例)
2.没有原型,占用内存。
- 更好的方式?
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div class="mydiv1"> <button style="background: red">按钮一</button> <button>按钮二</button> <p style="display: block;">div1</p> <p style="display: none;">div2</p> </div> <div class="mydiv2"> <button style="background: red">按钮一</button> <button>按钮二</button> <button>按钮三</button> <button>按钮四</button> <button>按钮五</button> <p style="display: block;">div1</p> <p style="display: none;">div2</p> <p style="display: none;">div3</p> <p style="display: none;">div4</p> <p style="display: none;">div5</p> </div> <button class="nextPre">点击我第一个选项卡下一页切换</button> <button class="autoPlay">点击按钮第二个选项卡有自动轮播功能</button> </body> <script> // 工厂模式 // function Tab(btns,ps){ // let tabNum = 4; // function psFor(){ // console.log("psFor...") // } // return { // tabNum, // psFor // } // } function Tab(btns, ps) { // 加原料 let obj = {} // let tabNum = 4; // function psFor(){ // console.log("psFor...") // } // 加工原料 obj.tabNum = 4; obj.psFor = function () { console.log("psFor...") } // 出厂 return obj; } let tab1 = Tab("参数一", "参数二"); // 自己逻辑 tab1.psFor(); let tab2 = Tab("参数一", "参数二"); // 自己逻辑 tab2.psFor(); </script> </html>
##new运算符
- new的特点:1.new只能函数 2.自动创建空对象; 3.this绑定到空对象;4 隐式返还this;
- 通过new来改造工厂模式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div class="mydiv1"> <button style="background: red">按钮一</button> <button>按钮二</button> <p style="display: block;">div1</p> <p style="display: none;">div2</p> </div> <div class="mydiv2"> <button style="background: red">按钮一</button> <button>按钮二</button> <button>按钮三</button> <button>按钮四</button> <button>按钮五</button> <p style="display: block;">div1</p> <p style="display: none;">div2</p> <p style="display: none;">div3</p> <p style="display: none;">div4</p> <p style="display: none;">div5</p> </div> <button class="nextPre">点击我第一个选项卡下一页切换</button> <button class="autoPlay">点击按钮第二个选项卡有自动轮播功能</button> </body> <script> // new 运算符; // let obj = {}; // let obj = new Object(); // new 1.执行函数;2.自动创建一个空对象; // 3.把空对象指向另外一对象;4、this绑定到这个空对象; // 5、隐式返还this; // function test(){ // console.log("test..."); // } // // test(); // new test(); // 工厂模式 // function Tab(btns, ps) { // // 加原料 // let obj = {} // // let tabNum = 4; // // function psFor(){ // // console.log("psFor...") // // } // // 加工原料 // obj.tabNum = 4; // obj.psFor = function () { // console.log("psFor...") // } // // 出厂 // return obj; // } // 构造函数;约定俗成首字母大写; constructor function Tab(){ // let obj = {} --->this; this.tabNum = 4; this.psFor = function(){ console.log("psFor...") } // return this; // return { // name:"张三" // } } // new 实例化;this-->实例化的对象; // let tab1 = new Tab(); // // console.log(tab1); // // tab1.psFor(); // let tab2 = new Tab(); // tab2.psFor(); // 仿写new运算符;new的运行原理; function myNew(constructor,...arg){ let obj = {}; // call / aplly /bind constructor.call(obj,...arg); obj.__proto__ = constructor.prototype; return obj; } let tab1 = myNew(Tab); tab1.psFor(); let tab2 = myNew(Tab); tab2.psFor(); </script> </html>
##构造函数
- 构造函数要通过new来调用 this指向Student
- 约定俗成构造函数首字母大写
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div class="mydiv1"> <button style="background: red">按钮一</button> <button>按钮二</button> <p style="display: block;">div1</p> <p style="display: none;">div2</p> </div> <div class="mydiv2"> <button style="background: red">按钮一</button> <button>按钮二</button> <button>按钮三</button> <button>按钮四</button> <button>按钮五</button> <p style="display: block;">div1</p> <p style="display: none;">div2</p> <p style="display: none;">div3</p> <p style="display: none;">div4</p> <p style="display: none;">div5</p> </div> <button class="nextPre">点击我第一个选项卡下一页切换</button> <button class="autoPlay">点击按钮第二个选项卡有自动轮播功能</button> </body> <script> // 工厂模式 // function Tab(){ // let obj = {}; // obj.name = "张三"; // obj.hobby = function(){ // console.log("喜欢篮球"); // } // return obj; // } // let tab1 = Tab(); // let tab2 = Tab(); // console.log(tab1.hobby===tab2.hobby); // 1.写法简单写;2.性能会更好; // 构造函数 function Tab() { this.name = "张三"; // this.hobby = function () { // console.log("喜欢篮球"); // } } // console.dir(Tab) // 提供公共空间;原型; Tab.prototype.hobby = function(){ console.log("喜欢篮球"); } // 原型会有一个预定义属性;constructor指向构造函数; // console.log(Tab.prototype.constructor === Tab); // Tab.prototype = { // constructor:Tab, // hobby(){ // console.log("喜欢篮球"); // } // } let tab1 = new Tab(); // console.log(tab1.__proto__===Tab.prototype)//true let tab2 = new Tab(); // 对象比较:1 值一样;2地址一样; // console.log(tab1.hobby===tab2.hobby); // console.log(tab1.name===tab2.name); // let obj = { // name:"张三" // } // let obj1 ={ // name:"张三" // }; // let a = 10; // let b = a; // let obj = new Object(); // let obj = Object.create({ // name:"张三", // age:20 // }) // console.log(obj) </script> </html>
##构造函数性能对比工厂函数
- 公共空间存放公共方法
##构造函数原型
### prototype原型
- 通过new实例化出来的对象其属性和行为来自两个部分,一部分来自构造函数,另一部分来自原型。
- 当声明一个函数的时候,同时也申明了一个原型 。
- 原型本身是一个对象。
- 对象属性方法查找规则;
### 面向对象编程
一、面相过程:注重解决问题的步骤,分析问题需要的每一步,实现函数依次调用;
二、面相对象:面向对象编程是用抽象方式创建基于现实世界模型的一种编程模式;
三、面相对象特性: 抽象、 继承、封装、多态
### 对象和类
一、对象:具体的某个事物;(如:小明、叮当猫)
二、类:一类事物的抽象;(如:人类、猫类)
## 总结
1)面向对象编程
2)工厂模式
3)new运算符
3)构造函数
4)原型
5)面相对象和面相过程编程
6)类和对象