JS高级
箭头函数
函数的简写 常做形参使用
代码展示
<script>
// 箭头函数
const fun1 = (Num) => Num + 1;
// 定义箭头函数,没有形参 没有返回值 2行实际业务
const fun2 = () => {
console.log('箭头函数');
}
// 没有形参 没有返回值 业务只有一行代码 大括号可以省略
const fun3 = () => console.log('箭头函数1');
fun3()
// 只有一个形参 没有返回值 业务只有一行代码
const fun4 = num1 => console.log(num1 + 1);
fun4(3)
// 两个或者多个参数(括号不能省略) 没有返回值 业务只有一行代码
const fun5 = (a, b) => console.log(a + b);
fun5(10, 1) //11
// 没有形参 有返回值 业务两行代码
const fun6 = () => {
let a = 100
return a + 100;
}
console.log(fun6()); //200
// 没有形参 有返回值 业务一行代码
const fun7 = () => {
return 100 + 101
}
console.log(fun7()); //201
// 没有形参 有返回值 业务一行代码 等价上述写法
const fun8 = () => 100 + 102; //相等与 return 100+102
console.log(fun8());
</script>
数组常见方法
1. forEach()
对数组进行遍历循环 forEach不能通过break打断
// forEach() 数组每个元素都执行一次回调函数。 = 类似以前的for forEach 高阶函数(可以接收一个形参-函数)
// for循环可以通过 break来打断、 forEach不能通过break打断
const arr = ['a', 'b', 'c'];
// 分别打印他们
arr.forEach(function (value, index) {
console.log(`值 是 ${value} 下标是 ${index}`);
});
arr.forEach((value, index) =>
console.log(`值 是 ${value} 下标是 ${index}`)
);
arr.forEach((value) => console.log(`值 是 ${value}`));
}
2.map()
根据原来的数组 来返回新的数组
map();
function map() {
// map 根据原来的数组 来返回新的数组
// 也会循环数组 在循环的回调函数中可以返回新的数据 组装成新的数组
// const arr = ['a', 'b', 'c'];
// 可以返回 ["我的字母是a","我的字母是b","我的字母是c"]
// const newArr = arr.map((value) => '我的字母是' + value); // [1,1,1]
// console.log(newArr);
// const list=[10,11,12];
// const newList=list.map(value=>value+1);// [11,12,13]
// console.log(newList);
// const objectArr=[{name:"悟空"},{name:"八戒"}];
// const newObjectArr=objectArr.map(value=>{
// // 1
// value.color="red";
// // 2
// return value
// })// [{name:"悟空",color:"red"},{name:"八戒",color:"red"}]
// console.log(newObjectArr);
const texts=["刘德华","郭德纲","林志颖"];
// // 返回 [<div>刘德华</div>,<div>郭德纲</div>,<div>林志颖</div>]
const newTexts=texts.map(value=>`<div>${value}</div>`);
// console.log(newTexts);
// // [<div>刘德华</div>,<div>郭德纲</div>,<div>林志颖</div>]
// // 把它转成字符串
const html=newTexts.join("");// <div>刘德华</div><div>郭德纲</div><div>林志颖</div>
// console.log(html);
document.body.innerHTML=html;
// 后面再说
// const renderHTML=value=>`<div>${value}</div>`
// document.body.innerHTML=["刘德华","郭德纲","林志颖"].map(renderHTML).join("");
}
3. 箭头函数 返回对象
箭头函数: const arr = (value) => ()
tips:注意这里的小括号 ,表示要返回小括号内的数据
尝试将数组内的元素转换成对象形式:
const arr = ['a', 'b', 'c'];
// 返回 [ {name:"a",name:"b",name:"c"} ]
const newArr = arr.map(value => ({ name: value }))
console.log(newArr); //[{name: 'a'}{name: 'b'}{name: 'c'}]
console.log(newArr[0]); //{name: 'a'}
<script>
const arr = ['a', 'b', 'c'];
// 返回 [ {name:"a",name:"b",name:"c"} ]
// const newArr=arr.map(value=>name:value );// 排除!
// const newArr=arr.map(value=>{name:value} ); // 思路正确 代码不正确
// const newArr=arr.map(value=>{
// name:value
// } ); // 思路正确 代码不正确
// const newArr=arr.map(value=>{
// name:value
// return undefined
// } ); // 思路正确 代码不正确
// const newArr=arr.map(value=>{
// console.log(1);
// console.log(2);
// } ); // 思路正确 代码不正确
// console.log(newArr);
// 箭头函数 会认为 这个大括号 是 块级空间 符号 而不是对象的符号
// const newArr1 = arr.map((value) => { name: value; }); // 这个大括号 是表示 对象的符号 还是表示 可以块级空间
// const newArr2=arr.map(value=> {
// console.log(123) ;
// console.log(123) ;
// console.log(123) ;
// return undefined
// } );
// // js认为 大括号是 块级空间 可以写js语句
// {
// console.log(123);
// console.log(123);
// console.log(123);
// }
// let obj={ // js会认为大括号是 对象的符号 里面不能写 语句
// console.log(123);
// console.log(123);
// console.log(123);
// }
// 箭头函数 的返回值 可以被省略
const func = (num) => num + 1; // 相当于 return num+1
const func1 = (num) => {
return num + 1;
}; // 这个大括号表示 块级空间
const func2 = (num) => {
num + 1;
}; // 会执行 num+1 但是没有返回值
const func3 = (num) => {
let num1 = num + 1;
let num2 = num1 + 2;
};
// console.log(func3());
const func4 = (num) => {
return { a: 123 };
};
// console.log(func4());
const func5 = (num) => {}; // 只要直接出现 大括号 就表示 块级空间 和它里面写什么代码没有关系
// console.log(func5());
const func6 = (num) => {
a: 2;
}; // 这个大括号就是对象(你的认为!! 浏览器还是一样 大括号就是块级空间)
// console.log(func6());
// 如果你真的看不懂 没有办法, 你先不要优雅!! 先用以前的function
// 如果你一定要在箭头函数中想要通过省略 return的方式来 返回对象,请你加上一个小括号
const func7=(num)=>({a:123});// => 右边加了小括号 表示想要返回 小括号里面的数据 return {a:123};
const func8=(num)=>{a:123};// => undefined
console.log(func7()); {a:123}
console.log(func8());// undefined
</script>
4.every()
- 会返回 true 或者 false
- 如果数组中每一个元素都符合条件,every返回true
- 如果空数组调用了every。 得到结果 也是true
<script>
every();
function every() {
// 会返回 true或者false
// 如果数组中每一个元素都复合条件,every返回true
// const arr = [1, 6, 3, 4];
// // 判断数组中每一个元素,是不是都小于 5 如果是 返回true
// // every当中的函数,要求每一个都return 了true 最后 every的返回值才是true
// const result = arr.every((value) => {
// if (value < 5) {
// return true;
// } else {
// return false;
// }
// });
// console.log(result);
// 有一个数组,存放每一个人 关于肺炎的检查结果
// const arr = [true, true, true, true, true]; // true就表示安全,false 中招
// 我想要判断一下 这个人群安不安全 (只要有一个为false,不安全) 要求每一个都为true才安全
// const result = arr.every((value) => {
// if (value === true) {
// return true;
// } else {
// return false;
// }
// });
// console.log(result);
//
// every 如果是空数组,调用every 直接返回true
let arr=[];
const result=arr.every(value=>console.log(12));// result = true
console.log(result);
// every:
// 会返回true或者false
// 要求数组中每一个元素都符号条件,every 得到true
// 如果空的数组调用了every。 得到结果 也是true
}
</script>
5.全选和全不选
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8" />
<title>08-全选和不全选-every</title>
<style>
* {
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #c0c0c0;
width: 500px;
margin: 100px auto;
text-align: center;
}
th {
background-color: #09c;
font: bold 16px '微软雅黑';
color: #fff;
height: 24px;
}
td {
border: 1px solid #d0d0d0;
color: #404060;
padding: 10px;
}
.allCheck {
width: 80px;
}
</style>
</head>
<body>
<table>
<tr>
<th class="allCheck">
<input type="checkbox" name="" id="checkAll" />
<span class="all">全选</span>
</th>
<th>商品</th>
<th>商家</th>
<th>价格</th>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck" />
</td>
<td>小米手机</td>
<td>小米</td>
<td>¥1999</td>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck" />
</td>
<td>小米净水器</td>
<td>小米</td>
<td>¥4999</td>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck" />
</td>
<td>小米电视</td>
<td>小米</td>
<td>¥5999</td>
</tr>
</table>
</body>
<script>
let checkAll = document.querySelector('#checkAll');
let checkboxList = document.querySelectorAll('.ck'); // checkboxList 现在是一个伪数组
checkboxList=[...checkboxList];// OK
// 商品全选点击 功能
checkAll.addEventListener('click', function () {
for (let index = 0; index < checkboxList.length; index++) {
checkboxList[index].checked = checkAll.checked;
}
});
// // 给每一个商品绑定点击事件
for (let index = 0; index < checkboxList.length; index++) {
checkboxList[index].addEventListener('click', function () {
// 判断是否达到了全选 条件
// 判断每一个小小的复选框的选中状态 如果都是true,那么就全选
// let checked = checkboxList.every((value) => {
// if (value.checked === true) {
// return true;
// } else {
// return false;
// }
// });
let checked = checkboxList.every((value) =>value.checked);
// 设置全选按钮即可
checkAll.checked = checked;
});
}
</script>
</html>
<!--
两个知识
1 伪数组转真正的数组 let newArr=[...伪数组] ;
2 every 要求数组的每一个元素都符号要求, every才返回true
使用场景, 商品全选 => 每一个小商品都选中, 全选才勾选!!
4 如果 数组 有every方法, list.every 看是不是undefined
不是的话 表示数组有 every方法 list.every() 调用
是 表示数组没有 every方法,不用list.every()
-->
6.伪数组转成真数组
const liList=[...伪数组]
const liList=[...lis];// 最简单的转伪数组的方式 先这么用
7.some()
检测数组,其中只要有一个元素符合条件,some返回true (every要求每一个都符合)
// some();
function some() {
// 检测数组,其中只要有一个元素符合条件,some返回true (every要求每一个都符合)
const arr = [1, 3, 4, 6, 2];
// 这个数组里面有没有元素大于6的
const result = arr.some((value) => value > 6);
console.log(result);
/*
every 和 some 一起记
every 要求全部都符合
some 最少有一个符合即可
*/
}
8.filter()
过滤 筛选出满足条件的数组.组成新数组
function filter() {
// 过滤, 过滤出满足条件的数据 =>新的数组
const arr = [1, 2, 3, 4, 5, 6, 7];
// 返回 奇数
// const newArr = arr.filter((value) => {
// // 如果你return 了 true 表示当前的value你想要
// if (value % 2 !== 0) {
// // value 1 2 3 4 5 6
// // value%2!==0 value=[1,3,5,7]
// // 奇数
// return true;
// } else {
// return false;
// }
// });
// const newArr = arr.filter((value) => value % 2 !== 0);
console.log(newArr);
}
9.待办列表优化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no"
/>
<title>11-待办列表.html</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #ccc;
}
ul {
list-style: none;
}
li {
padding: 20px;
text-align: left;
font-size: 30px;
border-bottom: 1px dashed #ccc;
display: flex;
justify-content: space-between;
align-items: center;
}
li input {
margin-right: 10px;
}
li button {
display: none;
padding: 5px;
}
li:hover button {
display: inline-block;
cursor: pointer;
}
.chk:checked + span {
text-decoration: line-through;
}
h1 {
margin-bottom: 10px;
}
.box {
background-color: #fff;
width: 60vw;
padding: 20px 20px 0;
margin: 50px auto;
}
.box .tool input {
width: 100%;
height: 50px;
text-indent: 20px;
font-size: 20px;
font-style: italic;
color: #666;
font-weight: 700;
}
section {
height: 50px;
display: flex;
justify-content: space-between;
align-items: center;
}
a {
text-decoration-color: #666;
color: inherit;
}
</style>
</head>
<body>
<div id="app" data-v-app="">
<div class="box">
<h1>待办列表</h1>
<div class="tool">
<input autofocus="" type="text" placeholder="请输入代办事项" />
</div>
<ul></ul>
<section>
<span>1 未完成</span><a href="#">清理 <b>0</b> 已完成</a>
</section>
</div>
</div>
<script>
const input = document.querySelector('.tool input');
const ul = document.querySelector('ul');
const unFinishSpan = document.querySelector('section span');
const finishA = document.querySelector('a b');
const a = document.querySelector('a');
let arr = [];
const strArr = localStorage.getItem('todo');
if (strArr) {
arr = JSON.parse(strArr);
}
render();
input.addEventListener('keydown', function (event) {
if (event.key === 'Enter') {
// input.value
arr.push({
text: input.value,
checked: false,
});
render();
input.value = '';
}
});
ul.addEventListener('click', function (event) {
const index = event.target.dataset.index;
if (event.target.className === 'chk') {
arr[index].checked = !arr[index].checked;
render();
} else if (event.target.nodeName === 'BUTTON') {
arr.splice(index, 1);
render();
}
});
a.addEventListener('click', function () {
let newArr = [];
for (let index = 0; index < arr.length; index++) {
if (!arr[index].checked) {
newArr.push(arr[index]);
}
}
arr = newArr;
render();
});
// 函数负责把数组数据渲染在页面上
function render() {
let html = ``;
for (let index = 0; index < arr.length; index++) {
const renderChecked = arr[index].checked ? 'checked' : '';
html += `
<li>
<div><input data-index="${index}" type="checkbox" class="chk" ${renderChecked} /><span class="false">${arr[index].text}</span></div>
<button data-index="${index}">X</button>
</li>
`;
}
ul.innerHTML = html;
localStorage.setItem('todo', JSON.stringify(arr));
statistics();
}
function statistics() {
// 未完成
unFinishSpan.innerText = arr.filter(value=>!value.checked).length + ' 未完成';
// 已经完成
finishA.innerText = arr.filter(value=>value.checked).length;
}
</script>
</body>
</html>
10.字面量-创建对象
- 优点:方便设置
- 缺点:不方便维护-修改
<script>
const obj1 = { name: '悟空1', tel: 123321 };
const name1 = 123;
const obj2 = { name: '悟空2', tel: 123322 };
const name2 = 123;
const obj3 = { name: '悟空3', tel: 123323 };
const name3 = 123;
const obj4 = { name: '悟空4', tel: 123324 };
const name4 = 123;
const obj5 = { name: '悟空5', tel: 123325 };
// 好处 方便
// 不方便维护-修改
// 不想要name属性,修改 username
</script>
11.工厂函数-创建对象
- 优点:容易维护
- 缺点:无法实现继承的作用
<script>
function createPerson(name, age, height) {
return {
// name: name,
username: name,
age: age,
height: height,
};
}
// 创建对象
const obj1 = createPerson('悟空', 18, 150);
const obj2 = createPerson('八戒', 20, 140);
const obj3 = createPerson('龙马', 30, 190);
console.log(obj1);
console.log(obj2);
console.log(obj3);
// 优点 容易维护
// name => username
// 弊端 无法实现 继承的作用!
</script>
12.构造函数-创建对象
<script>
// 专业术语
// 会把 createPerson 叫做 构造函数
// 会把 createPerson 创建出来的对象 叫做 实例
// 1 声明一个函数
function createPerson(name, age) {
// 2 给this赋值
this.name = name;
this.age = age;
// this.color="red";
}
// 2 通过new的方式来创建对象
const obj1 = new createPerson('悟空', 10);
console.log(obj1);
console.log(obj1.name);
console.log(obj1.age);
</script>
13.构造函数性能优化
<script>
function say() {
console.log('这个是say方法');
}
// 构造函数的首字母大写 - 行内编码规范
function CreatePerson(name) {
this.name = name; // 创建了name属性
// this.say = function () {
// console.log('这个是say方法');
// };
this.say = say; // say函数引用类型, 构造函数中的say 其实和外面的say内存地址一致的 同一个say方法
}
const obj1 = new CreatePerson('悟空');
const obj2 = new CreatePerson('八戒');
// obj1.say();
// obj2.say();
// 两个say的判断比较 是false 说明 两个say是在不同的内存空间上
// 两个say 占用了两个内存空间
// console.log(obj1.say === obj2.say); // false
console.log(obj1.say === obj2.say); // true
// 对于基本类型来说,= 就是复制了一份值
// let num=100;
// let num2=num;// 复制值 num和 num2占两给内存 各自不影响
// num2=1000;
// console.log(num);
// 对于引用类似 = 其实把地址拷贝了一份给新的对象 两个数据 公用一份数据
// let person1 = { name: '悟空' }; // person1 指向了 一个地址 0x1111 存放悟空
// let person2 = person1; // person2也指向了person1的地址 0x1111 person1和person2 通用一个数据
// 修改了person2 person1也会发生改变
// person2.name = '八戒';
// console.log(person1);
// person2 和person1 共同指向了同一个地址
// console.log(person1 === person2); // true
// let o={};// 开辟了一个内存
// let o2={};// 开辟了另外一个内存
// console.log(o===o2);// false 两个不同的内存地址
/*
构造函数想要解决 性能问题
1 一定会把方法-函数写在构造函数的外面
2 再通过this.say 指向外部的函数
*/
</script>
14.构造函数-性能问题
<script>
// 构造函数的 方法 都会通过类似的这种方式 来实现 多个实例的方法共享
function say() {
console.log('你好');
}
function CreatePerson(name) {
this.nickname = name;
this.say = say;
}
// function say() {
// console.log("学生你好");
// }
// function createStudent(params) {
// }
const obj1 = new CreatePerson('悟空');
const obj2 = new CreatePerson('八戒');
console.log(obj1);
console.log(obj2);
console.log(obj1.say === obj2.say); // true 这个代码是合理的 优化过
console.log(obj1.say === obj2.say); // false 不够好 性能不够好 两个say占据了两个内存
// 函数函数 方法提取出去 这套代码
// 优点: 方便代码维护、也解决了性能 obj1.say === obj2.say
// 缺点: 代码不够优雅 污染了全局变量 以后不能写 say方法,很容易就覆盖()
</script>
15.原型对象
- 原型对象 是任何构造函数都存在的一个对象 prototype
- 作用: 构造函数看是人, 原型对象 就是人的DNA
- 如果我们修改了DNA,那么通过构造函数创建实例都会一起发生修改
- 如果我们在DNA上新增了一些东西,对应实例一样会被新增
<script>
// 原型对象 是任何构造函数对存在的一个对象 prototype
// 作用: 构造函数看是人, 原型对象 就是人的DNA
// 如果我们修改了DNA,那么通过构造函数创建实例都会一起发生修改
// 如果我们在DNA上新增了一些东西,对应实例一样会被新增
function CreatePerson(name) {
this.name = name;
}
// 原型对象
// console.log(CreatePerson.prototype);
// 在DNA上新增 东西
CreatePerson.prototype.say = function () {
console.log('你好');
};
const obj1 = new CreatePerson('悟空');
const obj2 = new CreatePerson('八戒');
// obj1.say();
// obj2.say();
function CreateStudent() {}
CreateStudent.prototype.say = function () {
console.log('学生你好');
};
// console.log(obj1.say === obj2.say);// 没有性能问题
// 有污染全局变量的问题吗 没有
// CreatePerson.prototype.say
// CreateStudent.prototype.say
// 小结 原型对象-构造函数 一般情况
// 构造函数内只放属性 name 、age、color、height
// 对应原型上 都是放 方法 = 函数
</script>
16.构造函数-方法的 this
<script>
// 构造函数 创建不同人 大家有大家的名字, 共同一个行为 say => 说出自己的名称
function CreatePerson(name,height) {
this.name = name;
this.height=height;
// this.say = function () {
// // console.log(name);
// console.log(this.name);
// };
}
CreatePerson.prototype.say=function(){
// this 指向了实例
// 通过this 实现了 数据传递 =访问到另外一个函数(构造函数)中的数据
console.log(this.name,this.height); // 出错
}
const obj1 = new CreatePerson('八戒',100);
const obj2 = new CreatePerson('悟空',150);
obj1.say();
obj2.say();
</script>
17.面向对象初体验
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no"
/>
<title>20-面向对象-初体验.html</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.scale{
animation:ani-scale 3s linear infinite alternate ;
}
@keyframes ani-scale {
0%{
transform: scale(0.1);
}
100%{
transform: scale(2);
}
}
</style>
</head>
<body>
<button class="btn1">控制图片1</button>
<script>
/*
需求: 通过 new MyImg("图片地址") 页面上就会多一个图片标签
1 页面上多一个图片的本质代码
1 const img = document.createElement("img");
2 img.src="图片地址"
3 document.body.appendChild(img);
2 new的方式来创建图片
new MyImg 做了什么事情 => 调用了一个构造函数 MyImg
通过 点击了按钮,控制对应的图片 放大缩小效果
1 css来实现放大缩小
2 按钮 绑定点击事件
*/
// const img1 = new MyImg('./images/1.png'); // 页面上多一个图片标签
function MyImg(src) {
const img = document.createElement('img');
img.src = src;
document.body.appendChild(img);
this.dom=img;// 把图片dom元素 添加到 this对象的一个属性 dom属性上了
}
MyImg.prototype.scale=function(){
// 图片放大缩小的本质是不是给图片的dom元素 添加一个class
// 获取一下 上一个函数中的一个变量 img
// 原型上 想要获取另外一个函数中的变量
// console.log(this.dom);
this.dom.classList.add("scale");
}
const imgModel = new MyImg('./images/gotop.png');// 创建了一个对象
const btn1=document.querySelector(".btn1");
btn1.addEventListener("click",function () {
imgModel.scale();// 要调用这个对象的放大缩小的方法
})
</script>
</body>
</html>
18.面向对象的案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no"
/>
<title>23-面向对象案例.html</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
</style>
</head>
<body>
<button>修改颜色</button>
<script>
/*
需求:
1 通过行代码 const divModel = new Div("这个是普通的地址"); 页面中出现对应的一个div标签
2 给按钮绑定点击事件 触发了
divModel.changeColor("red"); 这个div的背景颜色变成红色
divModel.changeColor("yellow"); 这个div的背景颜色变成黄色
分析:
1 Div 是一个构造函数
2 Div 构造函数 在原型上有一个方法 changeColor
3 const divModel = new Div("这个是普通的地址");
这行代码实际的作用 页面中出现一个div
1 const div=document.createElement("div");
2 div.innerText="文本内容"
3 document.body.appendChild(div)
4 divModel.changeColor("yellow"); 这个div的背景颜色变成黄色
???.style.backgroundColor="yellow"
*/
function Div(text) {
const div = document.createElement('div');
div.innerText = text;
document.body.appendChild(div);
this.dom = div;
}
Div.prototype.changeColor = function (color) {
// this.dom = div;
this.dom.style.backgroundColor = color;
};
const button=document.querySelector("button");
const divModel1 = new Div('这个是普通的div1');
button.addEventListener("click",function () {
divModel1.changeColor("red");
// 新功能
divModel1.setFont("100px");// 希望div中的文字 大小变为100px
})
</script>
</body>
</html>