01_原型
- 每一个函数都有一个属于自己的原型
- 作用:我们会在原型内部放一些公共的方法,目的不是为了让构造函数去使用,而是为了让实例化对象去使用
-
function Person(name) { this.name = name } Person.prototype.sayHi = () => { console.log(111) } const p = new Person('QF666') p.sayHi() - 任何一个数组的构造函数都是 Array
- 任何一个对象的构造函数都是 Object
- 任何一个函数的构造函数都是 Function
- 需求:给数组扩展一个求最大值的方法
-
Array.prototype.getMax = function () { let max = this[0] for (let i = 1; i < this.length; i++) { if (max < this[i]) { max = this[i] } } return max } const arr1 = new Array(1, 2, 100, 5, 3, 4) const max = arr1.getMax() console.log(max) const arr2 = new Array(1, 2, 100, 5, 3, 4, 999) const max2 = arr2.getMax() console.log(max2)
02_万物皆对象
- JS中,万物都可以称为对象
- 对象:
- 含义1:一种数据格式{key:value , key2:value2}
- 含义2:某一类事务的实例(某一类内容中的真实个体)
03_原型链
- 查找对象的某一个属性:
- 先在对象内部开始查找,找到直接使用,然后停止查找
- 如果没有找到,会找对象的 obj.__ proto __ ,如果找到直接使用,然后停止查找
- 如果没有找到,会继续去对象的 __ proto__ ,查找,找到直接使用,然后停止查找;如果没有找到,就继续向上查找.....直到找到顶层作用对象 Object.prototype,找到就用,找不到就是 undefined
-
function Person (name) { this.name = name } Person.prototype.sayHi = function () { console.log(100) } const p = new Person('QF001') - 问题1:p的__ proto__指向谁?
- p是Person的实例化对象
- __ proto__指向自身构造函数的原型
- p.__ proto __ ===Person.prototype
-
console.log(p.__proto__ === Person.prototype)-----true
- 问题2:Person的 __ proto __ 指向谁?
- Person 是构造函数,本质上是函数
- 只要是一个函数,他就是Function的实例
- Person. __ proto__指向了他的构造函数的原型,构造函数是Function,那么构造函数的原型Function.prototype
- Person. __ proto__ ===Function.prototype
-
console.log(Person.__proto__ === Function.prototype)
- 问题3:Person.prototype的__ proto__指向谁?
- Person.prototype其实就是构造函数Person的原型对象,本质上就是对象
- 只要是一个对象,他就是Object的实例
- Person.prototype.__ proto__ 指向了他的构造函数的原型,构造函数Object,那么构造函数的原型Object.prototype
- Person.prototype.__ proto__ ===Object.prototype
-
console.log(Person.prototype.__proto__ === Object.prototype)
- 问题4:Function的__ proto__指向谁?
- Function是构造函数,本质上就是一个函数
- 只要是一个函数,他就是Function的实例
- Function.__ proto__指向了他的构造函数的原型,构造函数Function,那么构造函数的原型Function.prototype
- Function.__ proto__ ===Function.prototype
-
console.log(Function.__proto__ === Function.prototype)
- 问题5:Function.prototype的__ proto__指向了谁?
- Function.prototype其实就是构造函数Function的原型对象,本质上是对象
- 只要是对象,他就是Object的实例
- Function.prototype.__ proto__指向了他的构造函数的原型,构造函数Object,那么构造函数的原型Object.prototype
- Function.prototype.__ proto__ ===Object.prototype
- 问题6:Object的__ proto__指向了谁?
- Object是一个构造函数,本质上还是一个函数
- 只要是一个函数,那么他的构造函数就是Function
- Object.__ proto__指向了他的构造函数的原型,他的构造函数是Function,那么构造函数的原型 Function.prototype
- Object.__ proto__ === Function.prototype
-
console.log(Object.__proto__ === Function.prototype)
- 问题7:Object.prototype的__ proto__指向了谁?
- Object.prototype是构造函数Object的原型对象,本质上就是一个对象
- Object.prototype是JS顶层的对象
- Object.prototype.__ proto__ ===null
-
console.log(Object.prototype.__proto__)
04_判断数据类型
- typeof 判断基本数据类型
-
// 1. typeof console.log(typeof('123')) console.log(typeof(123)) console.log(typeof(true)) console.log(typeof(undefined)) console.log(typeof([1, 2, 3])) console.log(typeof({a:1}))
- constructor可以判断当前数据的构造函数是谁
- instanceof可以判断左边的构造函数是否等于右边的构造函数
- 语法:检测的数据 instanceof 狗凹函数
- 问题:不能判断undefined和null
-
/** * instanceof * 判断左边的构造函数是否等于右边的 */ console.log(arr instanceof Array) console.log(arr instanceof Function) console.log(obj instanceof Array) console.log(obj instanceof Object) Array.prototype.constructor = { a: 1 } console.log(arr instanceof Array) console.log(undefined instanceof Array) console.log(undefined instanceof Object) console.log(undefined instanceof Function)
- Object.prototype.toString.call (要判断的数据结构)------推荐使用
-
// 4. const arr = [1, 2, 3] const obj = { a: 1, b: 2 } /** * Object 这个构造函数的 原型内部 有一个 toString 的方法 * 这个方法能够帮我们将数据结构转为字符串的形式 '[object 数据结构]' * * 我们在使用的时候 如果需要判断其他数据类型, 需要使用 .call这个方法改变内部 this 指向 * * 这个方法任何数据类型都能准确判断(推荐使用) */ console.log(Object.prototype.toString.call([])) console.log(Object.prototype.toString.call(function () { })) console.log(Object.prototype.toString.call(undefined)) console.log(Object.prototype.toString.call(null))
05_轮播图(面向对象)
html
<!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>
* {
padding: 0;
margin: 0;
}
.banner {
width: 600px;
height: 400px;
border: 5px solid black;
margin: 200px auto;
/* overflow: hidden; */
position: relative;
}
.banner .img_box {
width: 500%;
height: 100%;
list-style: none;
display: flex;
position: absolute;
left: 0px;
}
.banner .img_box li {
width: 600px;
height: 100%;
font-size: 50px;
text-align: center;
line-height: 400px;
display: none;
}
.banner .img_box .active {
display: block;
}
.banner .focus {
width: 200px;
height: 30px;
background-color: white;
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 30px;
border-radius: 20px;
display: flex;
justify-content: space-evenly;
align-items: center;
list-style: none;
}
.banner .focus li {
width: 20px;
height: 20px;
border-radius: 50%;
background-color: rosybrown;
cursor: pointer;
}
.banner .focus .active {
background-color: red;
}
.left,
.right {
position: absolute;
transform: translateY(-50%);
font-size: 50px;
color: white;
top: 50%;
cursor: pointer;
}
.left {
left: 30px;
}
.right {
right: 30px;
}
</style>
</head>
<body>
<div class="banner" id="box1">
<!-- 放置所有轮播图的盒子 -->
<ul class="img_box">
<li class="active" style="background-color: burlywood;">1</li>
<li style="background-color: royalblue;">2</li>
<li style="background-color: greenyellow;">3</li>
<li style="background-color: pink;">4</li>
<li style="background-color: rgb(201, 255, 192);">5</li>
</ul>
<!-- 放置焦点的盒子 -->
<ol class="focus">
<!-- <li class="active"></li>
<li></li>
<li></li>
<li></li>
<li></li> -->
</ol>
<!-- 左右按钮 -->
<div class="left"><</div>
<div class="right">></div>
</div>
<div class="banner" id="box2">
<!-- 放置所有轮播图的盒子 -->
<ul class="img_box">
<li class="active" style="background-color: burlywood;">1</li>
<li style="background-color: royalblue;">2</li>
<li style="background-color: greenyellow;">3</li>
<li style="background-color: pink;">4</li>
<li style="background-color: turquoise;">5</li>
<li style="background-color: turquoise;">6</li>
</ul>
<!-- 放置焦点的盒子 -->
<ol class="focus">
<!-- <li class="active"></li>
<li></li>
<li></li>
<li></li>
<li></li> -->
</ol>
<!-- 左右按钮 -->
<div class="left"><</div>
<div class="right">></div>
</div>
<script src="./index.js"></script>
<script>
new Banner('#box1', {
des: 2000
})
new Banner('#box2', {
des: 5000
})
</script>
</body>
</html>
JS
/**
* 面向对象书写的小技巧
*
* 1. 获取元素, 准备变量, 以前是写在全局
* 面向对象就是把全局变量更改为写到 函数体内部 this.xxx == xxx
*
* 2. 书写方法 以前是写在全局
* 面向对象就是把全局函数, 书写在原型对象内部
*
*
* 面向过程
* 1. banner
* 2. imgBox
* 3. focus
* 4. index
* 5. timer
* 方法
* 1. 添加假图
* 2. 调整焦点
* 3. 自动轮播
* 4. 点击事件
*
* 面向对象
* 属性:
* this.banner = xxx
* this.imgBox = xxx
* this.focus = xxx
* this.index = xxx
* this.timer = xxx
* 方法:
* 1. 添加焦点
* 2. 自动轮播
* 3. 点击事件
*/
class Banner {
constructor(ele, options) {
this.banner = document.querySelector(ele);
this.imgBox = this.banner.querySelector(".img_box");
this.focus = this.banner.querySelector(".focus");
this.index = 0; // 记录当前在第个 图片, 默认第一个, 按照下标的形式存储
this.timer = 0; // 存储定时器ID
this.des = options.des // 存储传递进来的参数
this.setFocus(); // 1. 添加焦点
this.autoPlay(); // 2. 自动轮播
this.overOut(); // 3. 鼠标移入移出
this.clickBan();
}
// 原型
// 1. 添加焦点
setFocus() {
// 根据图片数量动态生成焦点
// 1. 获取图片数量
const imgNum = this.imgBox.children.length;
for (let i = 0; i < imgNum; i++) {
const newLi = document.createElement("li");
newLi.classList.add("new_li_item");
newLi.dataset.id = i;
if (i == 0) {
newLi.classList.add("active");
}
this.focus.appendChild(newLi);
}
}
// 1.5 切换
cut(type) {
// 就是给不同的 li 图片 添加类名
// 1. 函数调用时, 先将当前的 li对应的类名去掉
this.imgBox.children[this.index].classList.remove("active");
this.focus.children[this.index].classList.remove("active");
/**
* 使用场景
* 下一页(自动轮播也属于这种)
* 上一页
* 点击焦点, 跳转到对应页
*
* 我们约定, type 可以传递三个值
* 下一页调用时 传递 true
* 上一页调用时 传递 false
* 点焦点, 传递对应数字
*/
// 2. 判断
if (type === true) {
// 下一页
this.index++;
} else if (type === false) {
// 上一页
this.index--;
} else {
// 跳转对应页
this.index = type;
}
// 3. 边界判断
if (this.index > this.imgBox.children.length - 1) {
this.index = 0;
}
if (this.index < 0) {
this.index = this.imgBox.children.length - 1;
}
// 找到对应的项, 给他添加类名
this.imgBox.children[this.index].classList.add("active");
this.focus.children[this.index].classList.add("active");
}
// 2.自动轮播
autoPlay() {
this.timer = setInterval(() => {
// move 函数
// 调用一个 类似于 move 功能的函数
this.cut(true);
}, this.des);
}
// 3. 鼠标移入移出事件
overOut() {
this.banner.onmouseover = () => {
// 清除定时器
clearInterval(this.timer);
};
this.banner.onmouseout = () => {
// 重新打开自动轮播
this.autoPlay();
};
}
// 4. 点击事件
clickBan() {
this.banner.onclick = (e) => {
if (e.target.className == "right") {
// 下一页
this.cut(true);
}
if (e.target.className == "left") {
// 上一页
this.cut(false);
}
if (e.target.className == "new_li_item") {
// 跳转对应页
this.cut(e.target.dataset.id - 0);
}
};
}
}