一、面向对象介绍
1.了解面向对象+ 面向对象是我们的一种开发方式+ 面向过程: 一种关注过程的开发方式=> 在开发过程中, 我们要关注每一个细节, 步骤, 顺序+ 面向对象: 一种面向对象的开发方式=> 在开发过程中, 我们看看有没有一个对象能帮我们完成任务例子: 一份烤鸭+ 面向过程=> 所有事情都是我们自己做的=> 考虑顺序-> 先杀鸭子, 先考鸭子, 先切鸭子=> 考虑步骤-> 杀鸭子的时候, 先干什么, 后干什么=> 考虑细节-> 胡萝卜, 切宽窄程度-> 酱, 咸淡口味+ 面向对象=> 只需要点一份烤鸭=> 等待结果2.开发过程中的例子: 选项卡+ 面向过程=> 考虑获取那些元素=> 考虑给那些元素绑定点击事件=> 考虑点击的时候, 做什么+ 面向对象=> 考虑有没有一个对象能帮我们完成选项卡=> 如果有, 那么我就直接让这个对象帮我完成=> 如果没有, 我们就需要制造一个这样的对象来帮我完成+ 我们需要一个 "机器"=> 这个机器能给我生产一个对象=> 生产出来的对象能完成选项卡功能=> 我们只要准备好这个机器就可以了=> 本次开发过程中, 我们制造机器, 制造好以后, 用机器生成一个对象完成选项卡=> 当你第二次想进行选项卡开发的时候, 那么我们不需要再次制造机器了=> 只要用原先准备好的机器, 再次制造一个新的选项卡对象+ 我们制造 "机器" 得 过程, 就是面向对象封装的过程=> 面向对象的核心: 高内聚低耦合(就是对面向过程的高度封装)3.核心:+ 找到一个机器, 能批量生产对象+ 生产出来的对象, 每一个对象都有自己的属性和方法+ 每一个对象可能类似, 但是内容不太一样=> 构造函数=> 可以批量生产对象=> 可以向函数一样传递参数, 可以给每一个对象添加一些不同的内容=> 当你需要完成一个功能的时候, 我们先制造一个构造函数-> 利用构造函数去创建一个可以完成任务的对象-> 依赖这个对象完成功能+ 这个 "机器"(构造函数) 要生产有属性有方法的合理的对象=> 机器: 就是构造函数=> 属性: 直接写在构造函数体内=> 方法: 写在构造函数的原型上4.面向对象开发+ 选项卡1. 书写一个构造函数2. 创建一个能够完成选项卡的对象=> 属性: 选项卡中能够点击的按钮=> 属性: 选项卡中用于切换的盒子=> 方法: 控制点击的按钮添加点击事件, 给盒子进行切换操作3. 使用构造函数创建一个选项卡对象
二、创建对象的方式
<script>创建对象的方式1. 字面量方式创建对象+ var obj = { ... }+ 可以后期动态添加2. 内置构造函数创建对象+ var obj = new Object()+ 可以后期动态添加3. 工厂函数创建对象3-1. 制造一个工厂函数3-2. 使用工厂函数去创建对象4. 自定义构造函数创建对象4-1. 制造一个自定义构造函数4-2. 使用自定义构造函数去创建对象1. 字面量方式创建对象var obj = {name: 'Jack',age: 18,sayHi: function () { console.log('hello world') }}如果我想创建第二个对象var obj2 = {name: 'Rose',age: 20,sayHi: function () {console.log('hello world')}}2. 内置构造函数创建对象var obj = new Object()obj.name = 'Jack'obj.age = 18obj.sayHi = function () { console.log('hello world') }3. 工厂函数创建对象3-1. 创建工厂函数function createObj(name, age) {手动创建一个对象var obj = {}手动想里面添加属性obj.name = nameobj.age = ageobj.sayHi = function () { console.log('hello world') }手动返回这个对象return obj}3-2. 使用工厂函数去创建对象var obj1 = createObj('Jack', 18)var obj2 = createObj('Rose', 20)console.log(obj1, obj2)4. 自定义构造函数创建对象4-1. 制造一个自定义构造函数构造函数会自动创建对象, 自动返回这个对象我们只需要手动想里面添加内容就可以了function createObj(name, age) {自动创建对象手动向对象里面添加成员这里的 this 指向当前实例(new 前面的变量)this.name = namethis.age = agethis.sayHi = function () { console.log('hello world') }自动返回对象}4-2. 使用自定义构造函数去创建对象构造函数在使用的时候, 需要和 new 关键字连用如果不连用, 那么没有意义第一次调用 createObj 的时候, 和 new 关键字连用了我们 createObj 里面的 this 指向了 obj1函数内部的代码在执行的时候, 就是在向 obj1 添加了 name age 和 sayHi 三个成员var obj1 = new createObj('Jack', 18)第二次调用 createObj 的时候, 和 new 关键字连用了我们的 createObj 里面的 this 指向了 obj2函数内部的代码在执行的时候, 就是在向 obj2 添加了 name age 和 sayHi 三个成员var obj2 = new createObj('Rose', 20)console.log(obj1, obj2)</script>
三、构造函数的使用
<script>构造函数的使用1. 构造函数和普通函数没有区别=> 只不过在调用的时候和 new 关键字连用2. 书写构造函数, 函数名首字母大写=> 当你看到名字的时候, 就知道要和 new 关键字连用3. 调用的时候, 需要和 new 关键字连用=> 因为只有和 new 关键字连用的时候, 这个函数才会有自动创建和返回对象的能力=> 因为我们之所以书写构造函数, 就是为了使用它去批量生产对象=> 如果不和 new 关键字连用, 那么该函数没有创建对象的能力, 没有自动返回对象的能力4. 调用构造函数的时候, 如果不需要传递参数=> 可以不写最后的小括号=> 如果你需要传递参数, 那么必须写小括号=> 但是书写规范推荐我们都写上小括号5. 当你的函数名 和 new 关键字连用的时候=> 函数内部的 this 指向当前实例(new 关键字前面的变量)=> 我们直接在函数体内书写 this.xxx = 值-> 就是在向自动创建出来的对象里面添加内容6. 构造函数内部不要对边写 return=> 当你 return 了一个基本数据类型的时候, 写了白写=> 当你 return 了一个复杂数据类型的时候, 构造函数白写function person() {console.log('hello world')}function Person() {this.name = 'Jack'}3.var obj = new Person()console.log(obj)var obj2 = Person()console.log(obj2)4.var obj = new Person() console.log(obj)var obj2 = new Person console.log(obj2)6.function Person() {this.name = 'Jack'this.age = 18return 基本数据类型return 'true'return 复杂数据类型return [1, 2, 3]}var obj = new Person()console.log(obj)</script>
四、构造函数的不合理
<script>构造函数的不合理+ 当你在构造函数体内书写方法的时候=> 你需要向对象上添加方法的时候=> 只要创建一次对象(new 一次) 就会有一个函数在占用空间=> 创建 100 次对象, 会有 100 个一模一样的函数出现+ 100 个函数一模一样=> 但是其实里面有 99 个是重复的, 没有必要存在1. 准备一个构造函数function Person(name, age) {this.name = namethis.age = agethis.sayHi = function () { console.log('hello world') }}2. 创建对象var p1 = new Person('Jack', 18)var p2 = new Person('Rose', 20)console.log(p1, p2)调用两个对象的 sayHi 方法p1.sayHi()p2.sayHi()看一下是不是真的是两个对象console.log(p1 == p2) 两个对象里面的函数console.log(p1.sayHi)console.log(p2.sayHi)console.log(p1.sayHi == p2.sayHi) var p1 = new Person('Jack', 18)var p2 = new Person('Rose', 20)p1 第一次执行 Person 函数=> 会吧函数内部的 this 指向 p1=> 会吧函数体内的代码全部执行一遍=> 向 p1 上添加 name 属性=> 向 p1 上添加 age 属性=> 向 p1 上添加 sayHi 方法, 会创建一个函数出来p2 第二次执行 Person 函数=> 会吧函数内部的 this 指向 p2=> 会吧函数体内的代码全部执行一遍=> 向 p2 上添加 name 属性=> 向 p2 上添加 age 属性=> 向 p2 上添加 sayHi 方法, 会创建一个函数出来</script>
五、原型
<script>原型 prototype+ 定义: 每一个函数天生自带一个属性, 叫做 prototype, 是一个对象+ 构造函数也是函数, 也会有这个自带的空间 prototype+ 既然 prototype 是一个对象, 我们就可以使用对象操作的语法, 向里面添加一些内容对象+ 定义: 每一个对象, 在你访问他的成员的时候, 如果自己没有这个属性=> 会自动去所属构造函数的 prototype 上查找+ 自定义构造函数创建的对象也是对象, 当你访问某一个成员的时候=> 如果没有, 也会自动去所属构造函数的原型上查找=> 哪一个构造函数创建的对象, 这个对象就属于哪一个构造函数=> 因为构造函数在创建对象的过程, 我们起名为 实例化 的过程-> 创建出来的对象叫做这个构造函数的一个 实例化对象function Person() {}Person.prototype.sayHi = function () { console.log('我是 Person 原型上的方法') }console.log(Person.prototype)创建一个实例化对象因为 p1 是 Person 实例化出来的对象p1 就是属于 Person 这个构造函数的当你访问 p1 的 sayHi 成员的时候, p1 自己是没有的会自动去 Person 的 原型(prototype) 上查找var p1 = new Person()console.log(p1)p1.sayHi()创建第二个实例化对象因为 p2 也是 Person 的实例化对象p2 没有 sayHi 成员, 也会自动去 Person 的原型上查找var p2 = new Person()console.log(p2)p2.sayHi()p1 的 sayHi 方法和 p2 的 sayHi 方法都是使用的 Person 构造函数的原型上的方法我只要向 Person 的原型上添加一些方法所有的 Person 的每一个实例都可以使用并且使用的都是同一个函数, 不会出现浪费空间的行为console.log(p1.sayHi === p2.sayHi)
</script>
六、面向对象作业
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>* {margin: 0;padding: 0;}ul,ol,li {list-style: none;}.tab {width: 600px;height: 400px;border: 10px solid #333;margin: 50px auto;display: flex;flex-direction: column;}ul {height: 60px;display: flex;}ul>li {flex: 1;display: fex;justify-content: center;align-items: center;font-size: 40px;color: #fff;background-color: skyblue;cursor: pointer;}ul>li.active {background-color: orange;}ol {flex: 1;position: relative;}ol>li {position: absolute;left: 0;top: 0;width: 100%;height: 100%;font-size: 100px;color: #fff;background-color: purple;display: none;justify-content: center;align-items: center;}ol>li.active {display: flex;}</style>
</head><body><div class="tab" id="box"><ul><li class="active">1</li><li>2</li><li>3</li></ul><ol><li class="active">1</li><li>2</li><li>3</li></ol></div><div class="tab" id="box2"><ul><li class="active">1</li><li>2</li><li>3</li><li>4</li></ul><ol><li class="active">1</li><li>2</li><li>3</li><li>4</li></ol></div><div class="tab" id="box3"><ul><li class="active">1</li><li>2</li><li>3</li></ul><ol><li class="active">1</li><li>2</li><li>3</li></ol></div><script>function Tabs(ele) {this.ele = document.querySelector(ele);;this.btns = this.ele.querySelectorAll('ul>li')this.tabs = this.ele.querySelectorAll('ol>li')}Tabs.prototype.change = function () {var _this = this;for (var i = 0; i < this.btns.length; i++) {this.btns[i].setAttribute('index', i);this.btns[i].addEventListener('click', function () {console.log('点击我一下啊')for (var j = 0; j < _this.btns.length; j++) {_this.btns[j].className = '';_this.tabs[j].className = '';}this.className = 'active';var index = this.getAttribute('index') - 0;_this.tabs[index].className = 'active';})}}var t = new Tabs('#box')t.change()console.log(t);var t2 = new Tabs('#box2');t2.change();var t3 = new Tabs('#box3');t3.change();</script>
</body></html>