js高级
箭头函数:
定义一个箭头函数 没有形参没有返回值 2行代码:
const func2=()=>{
console.log('执行1');
console.log('执行2');
}
没有形参没有返回值 业务只有一行代码 大括号可以省略:
const func3=()=>console.log('执行fun3');
只有一个形参没有返回值 形参里面的括号可以省略 业务只有一行代码 (大括号可以省略)
const func4=(num)=>console.log('执行fun3');
const func4=num=>console.log('执行fun3')
两个或多个形参没有返回值 形参里面的括号不能省略 业务只有一行代码 大括号可以省略
const func5=(num,num2)=>console.log('执行fun3');
没有形参有返回值 业务两行代码
const func6=()=>{
let a=1;
return a+100;
}
没有形参有返回值 业务只有一行代码
const func7=()=>100+200;/* 相当于return100+200 */
const func7=()=>{
return 100+200;
}
数组常用方法:
forEach
高阶函数函数: 数组每个元素都执行一次回调函数。
类似于for 但是 foreach不可以通过break打破循环
<script>
const arr=['a','b','c'];
arr.forEach((value,index) => console.log(`值是${value},下标是${index}`));
arr.forEach(value => console.log(`值是${value}`));
</script>
map:
map根据原来的数组返回新数组;也会循环数组 在循环的回调函数中可以返回新的数据 组装成新的数组
需求:返回 ['这是a', '这是b', '这是c']
const arr = ['a', 'b', 'c'];
const newArr=arr.map(value=>'这是'+value);
console.log(newArr);
需求返回11 12 13
const list = ['10', '11', '12']
const newStr=list.map(value=>1+value*1);
console.log(newStr);
需求返回 {name:'悟空',color:'red'},{name:'八戒',color:'red'}
const objectArr=[{name:'悟空'},{name:'八戒'}];
const newobjectArr=objectArr.map(value=>{
value.color='red';
return value;
})
需求转为字符串输出到页面
const texts=["刘德华","郭德纲","林志颖"];
const newtexts=texts.map(value=>`<div>${value}</div>`)
console.log(newtexts);
const html=newtexts.join('')/* 转为字符串输出到页面 */
document.body.innerHTML=html;
需求是变成返回对象数组 两种方式第一种写一个返回值 第二种在对象外边加()
const newArr1=arr1.map(value=>{
return {name:value}
})
const newArr2=arr1.map(value=>({name:value}))
console.log(newArr1);
console.log(newArr2);
}
every():
检测数组中每个元素是否都符合条件 返回值是true或者false
判断数组中每一个元素,是不是都小于 5 如果是 返回true
const arr = [1, 3, 2, 8, 7];
/* 每个都return了结果才为真 */
const result = arr.every((value) => {
if (value > 5) {
return true;
} else {
return false;
}
});
如果是空数组,调用every 直接返回true
// every 如果是空数组,调用every 直接返回true
let arr1 = [];
const result1 = arr1.every((value) => console.log(1));
console.log(result1);
some: 检测数组,其中只要有一个元素符合条件,some返回true (every要求每一个都符合)
<script>
const arr = [1, 3, 4, 6, 10];
const result=arr.some((value)=>value>6);
console.log(result);/* 返回值为真 */
</script>
filter
过滤出满足条件的数据:返回值为新数组
filter();
function filter() {
// 过滤, 过滤出满足条件的数据 =>新的数组
const arr = [0, 1, 2, 5, 8, 9];
// const newarr=arr.filter(value=>{
// if (value%2!==0) {
// return true
// }else{
// return false
// }
// })
const newarr = arr.filter((value) => value % 2 !== 0);
console.log(newarr);
}
待办列表复选框选中为已完成 未选择为未完成
function statistics() {
// 未完成数组中value属性为checked的值 值为真是已完成 值为假是未完成
unFinishSpan.innerText=arr.filter((value)=>!value.checked).length + ' 未完成';
// 已经完成
finishA.innerText = arr.filter(value=>value.checked).length;
}
面向对象:
编程行业内通用的写项目级别的代码思维,引导我们编写高质量的代码。
属性:数据 ;行为
创建对象的方式:
字面量:不适合创建多个同样类型的对象
const obj={name:'你',age:'18'}
工厂函数:无法实现继承
function createPerson(name,age,height) {
return{
username:name,
age:age,
height:height
}
}
const obj1=createPerson('陈多多','18','165')
const obj2=createPerson('张一琼','20','180')
构造函数:可以方便的创建对象 拥有血缘关系
会把 createPerson 叫做 构造函数 会把 createPerson 创建出来的对象 叫做 实例
1.开辟空间
2.将新的创建的对象对象构造函数中的this 给this赋值相当于给obj赋值
3.代码不够优雅 污染了全局变量 以后不能写 say方法,很容易就覆盖()
<script>
function say() {
console.log('你好');
}
function CreatPerson(name,age) {
/* 用this赋值 赋值后的值和形参保持一致*/
this.name=name;
this.age=age;
// this.say=function () {
// console.log(1);
// }
}
/* 通过new的方式来创建对象 */
const obj1=new CreatPerson('陈多多',18)
console.log(obj1);
console.log(obj1.name);
console.log(obj1.age);
console.log(obj1.say === obj2.say); // true 这个代码是合理的 优化过
/* console.log(obj1.say === obj2.say); */ // false 不够好 性能不够好 两个say占据了两个内存
</script>
原型模式: 原型对象 是任何构造函数对存在的一个对象 prototype
动画效果:点击按钮图片变大
.scale{
animation:ani-scale 3s linear infinite alternate;
}
@keyframes ani-scale {
0%{
transform: scale(0.3);
}
100%{
transform: scale(2);
}
}
function MyImg(src) {
/* 创建dom元素 */
const img=document.createElement('img');
/* dom元素修改地址 */
img.src=src;
/* 将dom元素添加在body里面 */
document.body.appendChild(img);
/* 调用this才能用到修改函数中 */
this.dom=img
}
MyImg.prototype.scale=function () {
this.dom.classList.add('scale')
}
const img1=new MyImg('images/9.5/01.jpg');/* 创建对象 */
const btn=document.querySelector('button');
btn.addEventListener('click',function () {
/* 对象调用scale方法 */
img1.scale();
})
原型-继承-call:
属性的继承用call
call借调:可以让一个对象借用另外一个对象的方法
obj.skill.call(obj2) obj2借用obj的skill这个方法
<script>
function Parent(name,age,height) {
this.name=name;
this.age=age;
this.height=height;
}
function Son(name,age,height,color) {
/* 儿子想要继承父亲的属性 */
/* call借用父亲的name,age,height属性this指的是Son */
Parent.call(this,name,age,height);
this.color=color;
}
const son1=new Son('小乐','18',180,'pink');
const Parent1=new Parent('老陈','38',185);
console.log(son1);
console.log(Parent1);
方法的继承:儿子想要继承父亲的原型方法直接令儿子的原型方法等于父亲的原型方法
Son.prototype.say=Parent.prototype.say
/* 父亲原型的方法儿子想调用 */
Parent.prototype.say=function(say) {
console.log(this.name+say);
}
/* 儿子想要继承父亲的属性直接令儿子的原型方法等于父亲的原型方法 */
Son.prototype.say=Parent.prototype.say;
ES6:
ES6的函数默认值
<script>
/* 函数默认值直接讲默认值写在形参那里 */
function show(str='你好',msg='大家好') {
/* 输出值 */
console.log(str,msg);
}
/* 调用函数 */
show();/* 返回默认值 */
show('我很好')/* str值改变 msg值不变 */
show('我很好','你也很好')
</script>
对象简写:
变量名和对象的属性一致可以简写
/* 变量名和对象的属性一致可以简写 */
const username = "小张";
const age = 18;
const height = 180;
const say = function () {
console.log("say");
};
const obj = {
username,
age,
height,
say,
show() {
console.log("show");
},
};
console.log(obj);
对象方法简写:
obj = {show() {console.log("show")}},
解构:
数组结构:
const arr = [1, 2, 3, 4];
/* 数组解构 数组中没有的值e 现在e=30相当于默认值 */
const [a, b, c, d, e = 30] = arr;
console.log(a, b, c, d, e);
对象解构:
/* 对象解构 */
const obj={
name:'小张',
age:'18'
}
/* height=180 是默认值 原来对象中没有的值 如果对象中有值 这个height等于对象中height值 */
const {name,age,height=180}=obj;
console.log(name,age,height);
拓展运算符-剩余运算符-延展运算符 ...
数组中获取剩下的值 返回值是一个数组,如果没有剩下值返回时[]
const [a,b,...d]=[1,3,2,1,8,6]
console.log(a,b,d);/* 输出结果是a=1;b=3 d=[2,1,8,6] 如果没有剩下值返回时[]*/
对象中获取剩下的值 返回值是一个对象,如果没有剩下值返回时{}
const {a,...d}={a:1,b:2,c:3}
console.log(a,d);/* a=1;d={b:2,c:3} 如果没有剩下值返回时{} */
函数中获取剩下的值:
function calc(...args) {
// console.log(args);/* 返回值时一个数组[1,2] */
let sum=0;
args.forEach(value=>sum+=value);
console.log(sum);
}
calc(1,2,3,4)/* 返回值时是10*/
...的展开用法-延展性:
要求:新创建对象有obj的属性还有其他属性
const obj = {
username: '悟空',
height: 200,
};
/* 开辟了新空间 新的对象和旧的对象占用两个不同的空间 */
const newobj={...obj,color:'pink'};
newobj.age=18;
console.log(newobj,obj);
要求新展开的数组含有旧数组的属性:
const arr=['a','b','c','d']
const newarr=[...arr,'e'];/* e添加在旧数组后面 */
const newarr1=['w',...arr];/* w添加在旧数组前边 */
console.log(arr,newarr);
/* 在数组中添加数据也可以用 newarr.push;newarr.unshift;newarr.splice */
数组去重:
方法一:some选出数组中重复的数据,如果有重复弹框重复,没有重复就添加
/* some检测数组中符合条件的个数
返回值为true判断数组中的值等不等于input输入框的值 this.value相当于input.value*/
const isHave=arr.some(value=>value===this.value);/* 一定要用全等 */
if (isHave) {
console.log('数据重复');
}else{
arr.push(this.value);
/* 数组改变重新渲染页面 */
render()
}
方法二:filter过滤出数组中不重复的数据,组成新数组 让旧数组等于新数组 再添加数据
const newArr=arr.filter(value=>value!==this.value);
/* 让arr=newarr就过滤掉重复的值了 数组新增数值 重新调用函数 */
arr=newArr;
arr.push(this.value);
render()
方法三:遍历数组,判断是否有重复数据
if (event.key === "Enter") {
let isHave = false; /* 首先定义没有重复 */
for (let index = 0; index < arr.length; index++) {
if (arr[index] === input.value) {
/* 就是有重复,有重复就退出循环了*/
isHave = true;
break;
}
}
/* 如果isHave=true那就是有重复 没有重复的时候添加数据就行 */
if (isHave) {
console.log(isHave);
} else {
console.log(isHave);
arr.push(input.value);
render();
}
}
方法四:定义一个i=-1,遍历数组,数组中数据有重复的i=index索引,再删除这个重复的数据
let i=-1;
for (let index = 0; index < arr.length; index++) {
if (arr[index]===this.value) {
/* 此时i的值是数组里面的索引*/
i=index;
console.log(i);
break;
}
}
/* 判断i=-1没有相同的可以直接添加 i=index有相同的先删除相同的再添加 */
if (i===-1) {
arr.push(this.value);
render();
}
else{
arr.splice(i,1);
arr.push(this.value);
render()
}
方法五:set数组去重:
const set = new Set(arr); /* 数组转为对象 */
set.add(this.value); /* 对象中添加数据 */
arr = [...set];/* 对象转为数组 */
render();
set对象:主要功能是自己内部去重。
数组用set去重:set是一个对象
<script>
const beforeArr=['a','b',1,3,9];
const set=new Set(beforeArr);/* 数组转为对象 */
set.add(1);/* set添加数据 , set对象重复的数据自动去重*/
set.add(5);
console.log(set);
const arr=[...set];/*对象转为数组 */
console.log(arr);
</script>
this指向:
函数调用模式:this指向window
function func() {
console.log(this);/* this指向windows */
}
func();
对象:谁调用this就指向谁:
const obj = {
name: "张张",
say() {
console.log(this);/* this指向obj */
},
};
obj.say()
构造函数调用模式:this指向新创建的实例对象
function Person() {
this.name='张总'
}
Person.prototype.say=function(){
console.log(this);
}
const p1=new Person();
p1.say()/* this指的是实例 谁调用this就指向谁 */
箭头函数this指向:基本指向window
const func1 = () => {
console.log(this);/* this指向window */
};
func1()
const obj = {
name: "张张",
say:()=> {
console.log(this); /* this指向window */
},
};
obj.say();
const btn=document.querySelector('button');
btn.addEventListener('click',()=>{
console.log(this);/* 指向window */
})
call、apply、bind可以修改this指向 谁调用了这个方法this就是谁
const obj = {
name: "刘能",
skill() {
console.log(this.name + "口吃");
},
};
const person = {
name: "广坤",
};
call:修改this指向和传递参数
obj.skill.call(person,1,2);/* call传参 */
apply:修改this指向和传递参数 第二个位置必须要传递的是[数组]
obj.skill.apply(person,[1,2]);/* skill传参 */
用apply计算最大值并不是主流方式:
/* 借用 Math.max方法 目的不是修改this指向 而是 计算数组最大值 第一个传递时是null */
const arr=[1,2,3,4];
const max = Math.max.apply(null,arr);
主流方式:
/* 主流方式 */
console.log(Math.max(...arr));
bind:修改this指向和传递参数
const func1 = obj.skill.bind(person);
func1(1,2);/* bind传参 */
ES6创建对象:用class
class Person {
/* 构造函数 对象的属性写在这里 */
constructor(name, color) {
this.name = name;
this.color = color;
}
/* 对象的方法写在这里 */
say() {
console.log('say');
}
fly(){
console.log('fly');
}
}
const superMan=new Person('超人','红色'); /* constructor 会在 new Person的时候触发 */
const superMan1=new Person('超人1','粉色');
// superMan.say();
// superMan1.say();
console.log(superMan.say()===superMan1.say());/* 返回值是true方法不占内存 */
superMan.fly();
console.log(superMan);
</script>
ES6继承:
方法的继承用 class Son extends Parent(儿子继承父亲 方法)
属性的继承用:super(属性1,属性2)
<script>
class Parent{
constructor(name,height){
this.name=name;
this.height=height;
}
say(){
console.log('说话');
}
fly(){
console.log('起飞');
}
sleep(){
console.log('睡觉');
}
};
class Son extends Parent{/* 继承父亲的所有方法 */
constructor(name,height,color){
super(name,height);/* 继承父亲的name,height属性 */
this.color=color;
}
sleep=null;/* 覆盖父亲的这个方法 等于说儿子不用父亲的这个方法 */
}
const son1=new Son('儿子','180','粉色');
son1.say();
son1.fly();
console.log(son1);
</script>
class的三种书写方式:
class Person{
say1() {/* 性能最好最推荐 */
console.log('say1');
}
say2=function(){
console.log('s2');
}
say3=()=>{
console.log('s3');
}
}
const p1=new Person();
const p2=new Person();
console.log(p1.say1===p2.say1);/* true p1 和 p2 say1方法是同一个-节省内存 */
console.log(p1.say2===p2.say2);/* false p1 和 p2 say2方法不是同一个-性能不好*/
console.log(p1.say3===p2.say3);/* false p1 和 p2 say2方法不是同一个-性能不好*/
原型链:
js内置有构造函数 数组Array和构造对象Object;
给js内置的Array数据原型上添加一个方法;万物皆对象 给对象添加新方法 其他可以调用这个方法
Array.prototype.show=function(){
console.log('会说话');
}
Object.prototype.fly=function(){
console.log('这是新增的原型方法');
}
const arr=[1,2,3];
/* 调用这个方法 */
arr.show();
arr.fly();
console.log(arr);/* arr拥有两种方法 show和fly 基于原型链来 最底层是object */
原型链:
它可以通过 prototype 来 找到被它继承父亲的方法
如果一个对象从底层触发 可以通过 prototype 一层一层往上找到 继承的关系 = 原型链
<script>
const obj = {
username: "悟空",
say() {
console.log("这个是say方法");
},
};
Object.prototype.show = function () {
console.log("这是show方法");
};
console.dir(document.querySelector("div"));
/* 第一层:HTMLDivElement
第二层:HTMLElement
第三层:Element
第四层:Node
第五层: EventTarget
第六层:Object */
</script>