01-JavaScript 高级进阶 第三天
1.今日目标
箭头函数(重点)
instanceof 和 constructor
es6 class 和 继承
闭包
2.箭头函数 重点
格式—定义语法
// 箭头函数是匿名函数,一般做为参数传递
// let test = function (a,b){
// let sum = a + b
// return sum
// }
// let test = (参数) => {函数体}
// 几个小细节
// 1.如果函数体只有一句,那么可以省略{},同时默认会返回函数体的结果,不能写return
// 2.如果只有一个参数,那么可以省略()
// 3.如果没有参数,()也不能省略
// let test = (a,b) => a + b // 不能有大括号
let test = a => a + 10
let res = test(100)
console.log(res)
特性
// 箭头函数自己没有this
// 箭头函数的this是确定的,况且永远不变
// 箭头函数中的this指向 创建这个箭头函数所在对象 的上下文
let obj = {
name: 'jack',
say: function () {
return () => {
console.log(this) // obj
}
}
}
let fn = obj.say()
fn() // obj {name: "jack", say: ƒ}
let newobj = {}
newobj.fun = fn
newobj.fun() // obj {name: "jack", say: ƒ}
let rose = {
name: 'rose'
}
fn.call(rose) // obj {name: "jack", say: ƒ} 无法改变
3.instanceof 和 constructor
判断一个实例是否属于某个构造函数
// 构造函数
function Person() {
}
const p1 = new Person();
console.log(p1 instanceof Person);
console.log(p1.__proto__.constructor === Person);
4.es6 class(重点)
es6的class 的出现 基本上可以替代了es5的构造函数和原型,使之代码结构上更加简洁。
关键字
- class
- 属性
- 方法
- 继承 extends
- 构造函数 constructor
- 方法重写 override:子类方法覆盖父类,super.父类方法()
- 父类的构造函数 super :子类有构造方法且使用this前,必须使用super()
完整代码体验
class Person {
// 构造方法
constructor(name) {
// 属性
this.name = name;
}
// 方法
say() {
console.log(this.name);
}
}
// 继承
class Student extends Person{
constructor(name,height){
// console.log(this); // 语法错误:必须先调用super()才能使用this
super(name);
this.height=height;
}
}
const s1=new Student("八神",180);
s1.say(); // 八神
class Saler extends Person{
constructor(name,age){
super(name);
this.age = age;
}
// 覆盖(重写)
say(){
// 访问父类方法
super.say(); // 马云
console.log(this.age);
}
}
const s2 = new Saler('马云',50);
s2.say(); // 50
Tab栏切换
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>tab栏切换</title>
<style>
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
.box {
width: 400px;
height: 300px;
border: 1px solid #ccc;
margin: 100px auto;
}
.hd {
height: 45px;
}
.hd span {
display: inline-block;
/*将行内元素转换成行内块元素,宽高才起作用*/
width: 90px;
background-color: pink;
line-height: 45px;
text-align: center;
cursor: pointer;
}
.hd span.current {
/*交集选择器,标签指定式选择器*/
background-color: purple;
/*紫色*/
}
.bd li {
height: 255px;
background-color: purple;
display: none;
/*设置隐藏*/
}
.bd li.current {
display: block;
/*显示*/
}
</style>
<script src="js/TabExchange.js"></script>
</head>
<body>
<div class="box" id="box">
<div class="hd">
<span class="current">体育</span>
<span>娱乐</span>
<span>新闻</span>
<span>综合</span>
</div>
<div class="bd">
<ul id="list">
<li class="current">我是体育模块</li>
<li>我的娱乐模块</li>
<li id="li3">我是新闻模块</li>
<li>我是综合模块</li>
</ul>
</div>
</div>
<script>
let tab = new TabExchange('box', 'current');
console.dir(tab);
</script>
</body>
</html>
class TabExchange {
// 构造函数
constructor(id, className) {
// 获取id对应的元素:规范,属于最外层
this.id = document.querySelector(`#${id}`)
// 规定内部有两层解构:div>span
this.hd = this.id.querySelectorAll('div>span')
// 规范内部有两层解构:div>ul>li
this.bd = this.id.querySelectorAll('div>ul>li')
// 保存当前要处理的样式类
this.style = className;
// 调用自己的tabClick 方法处理点击事件
this.tabClick();
}
// 绑定点击事件
tabClick() {
// 因为接下来要绑定事件,事件里面也会出现this,所以先定义变量that来保存当前TabExchange对象的this
let that = this
// 循环遍历,绑定事件,并进行事件处理
this.hd.forEach(function (item, key) {
// item就是span,key就是span的下标
item.addEventListener('click', function () {
// 排他:清空hd全部样式
that.hd.forEach(function (item1) {
item1.classList.remove(that.style)
})
// 清空bd的所有样式
that.bd.forEach(function (item2) {
item2.classList.remove(that.style)
})
// 给当前事件元素添加样式
that.hd[key].classList.add(that.style)
that.bd[key].classList.add(that.style)
})
})
}
}
元素创建继承
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.element {
width: 200px;
height: 200px;
border-radius: 50%;
border: 10px solid #00ffff;
text-align: center;
font-size: 30px;
line-height: 200px;
overflow: hidden;
float: left;
}
</style>
<body>
<script>
// 创建一个类:可以创建普通元素,并且可以实现将元素挂到指定父元素下
class CreateElement {
// 构造函数,传入标签名,文本内容,和元素默认类名
constructor(element, text, className = 'element') {
// 1.创建元素
const node = document.createElement(element)
// 2.添加类名
node.classList.add(className)
// 3.添加文本内容(双标签有效,单标签无效)
node.innerText = text
// 4.将创建的元素节点存入到属性node
this.node = node
}
// 将当前创建的元素 添加到指定父元素下
appendTo(selector) {
// 获取父元素
const parent = document.querySelector(selector)
// 添加子元素
parent.appendChild(this.node)
}
}
// 直接创建一个普通元素
const div = new CreateElement('div', '做人开心就好')
div.appendTo('body')
// 图片标签不适用于普通元素创建(有属性src),但是想使用默认的样式和创建过程
// 创建子类 继承 父类
class CreateImg extends CreateElement {
// 自己的构造函数:只需要传入图片
constructor(src, className = 'element') {
// 父类构造函数
super('img', '', className)
// 给创建的元素增加src属性
this.node.src = src
}
}
// 改变了创建的内容,但是可以直接应用父类继承的方法
const img = new CreateImg('images/02.jpg')
img.appendTo('body')
</script>
</body>
</html>
5.闭包
概念
在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),只要出现引用了外部变量的函数,那么这个现象就叫做闭包
作用
- 让数据变得更加的安全
- 优化代码
- 函数内返回了另外一个函数
使用闭包前
<body>
<button>自增</button>
<h1></h1>
<script>
const btn = document.querySelector("button");
const h1 = document.querySelector("h1");
let num = 0;
let arr = [{ name: "金" }, { name: "木" }, { name: "水" }, { name: "火" }, { name: "土" }];
h1.innerText = arr[num].name;
btn.onclick = function () {
num++;
if (num >= arr.length) {
num = 0;
}
h1.innerText = arr[num].name;
}
</script>
</body>
使用闭包后
<body>
<button>自增</button>
<h1></h1>
<script>
const btn = document.querySelector("button");
const h1 = document.querySelector("h1");
function setElements() {
let num = -1;
let arr = [{ name: "金" }, { name: "木" }, { name: "水" }, { name: "火" }, { name: "土" }];
return function () {
num++;
if (num >= arr.length) {
num = 0;
}
return arr[num].name;
}
}
const getElement=setElements();
h1.innerText = getElement();
btn.onclick = function () {
h1.innerText = getElement();
}
</script>
</body>