前端笔记(js篇)
一、变量
类型和类型检测:
1、值/基本类型:Number、Boolean、String、Null、Undefined、Symbol(es6)、BigInt(es10)
2、对象/引用类型:Object(Array、Date、RegExp、function)
typeof:基本类型除了Null都可以用typeof() 识别,Null和引用类型被统一识别为object,function被识别为function
instanceof:用于引用类型的检测,返回布尔值,console.log([] instranceof Array) //true
constructor:除了null和undefined,constructor能检测所有基本类型和引用类型,但当对象的原型更改之后,constructor便失效了。console.log([].constructor === Array) //true
Object.prototype.toString.call():可用于检测js所有的数据类型。Object.prototype.toString.call('str') //[object String]
作用域:全局、函数、块,如果一个变量没声明就使用会层层向上寻找,找不到则报未定义错误。
闭包和变量引用:所有自由变量的查找,是在函数定义的地方,向上级作用域查找,不是在函数执行的地方!!!
this:this取什么值是在函数执行的时候确认的,不是定义的时候确认,箭头函数里面的this指向上级作用域的this
其他补充:
==运算符(会隐式转换)和===运算符:除了==null 之外,尽量用===,a==null相当于(a===null || a===undefined),反之亦然
truly和falsely变量:常用于if语句和逻辑运算,0、NaN、''、null、undefined、false等都是falsely变量,除此都是truly变量。let a='' || 123 //a为123
二、循环和深拷贝
循环:
let list=[1,2,3,4]; /* map循环: 概述:将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个新数组返回。 参数1:是个函数,接收三个参数,(当前成员,当前位置,数组本身)=>返回值 参数2:map的第二个参数用来绑定回调函数内部的this变量 */ let newList=list.map(n=> n+1); console.log(newList) //[2,3,4,5] //foreach循环,与map类似,但不返回值,参考map使用 /* filter循环: 概述:用于过滤数组成员,满足条件的成员组成一个新数组返回。 参数与map一样 */ let oddList=list.filter(n=> n%2!=0); console.log(oddList) //[1,3] /* reduce方法和reduceRight: reduceRight是从右往左开始,其他一样。 概述:依次处理数组的每个成员,最终累计为一个值 参数:参数一为函数,参数二为累计初始值 函数参数:(累积变量,当前变量,当前位置,原数组),前两个必须 累积变量,默认为数组的第一个成员 当前变量,默认为数组的第二个成员 当前位置(从0开始) 原数组 */ let total=list.reduce((a,b)=> a+b,10); console.log(total) //20 let maxNum=[3,6,7,2,5].reduceRight((a,b)=> a>b?a:b); console.log(maxNum) //7
拷贝:
展开运算符、Object.assign、数组的concat方法严格来说不是深拷贝,在对象或数组结构是一级基本属性并且属性值不是引用类型的时候才是深拷贝
let arr1=[1,2,3]; //数组拷贝一:使用展开运算符 let arr2=[...arr1]; //数组拷贝二:使用concat方法 let arr3=[].concat(arr1); let obj1={name:'jiangnan',job:'前端开发'}; //对象拷贝一:展开运算符 let obj2={...obj1}; //对象拷贝二:Object.assign() let obj3=Object.assign(obj1); //对象拷贝三:JSON.stringify和JSON.parse可以做深拷贝,但如果对象里有function或RegExp这些就不能用这种方法了。 let obj4 = JSON.parse(JSON.stringify(obj1));
深拷贝,适用于数组和对象
function deepClone(obj={}){ if(typeof obj !== "object" || obj == null){ return obj; } let result = obj instanceof Array ? [] : {}; for(let key in obj){ if(obj.hasOwnProperty(key)){ result[key] = deepClone(obj[key]); } } return result; }
三、类和原型
类:
/* 类:可以理解为一个对象,对象有属性、方法 子类:所有类都是object的子类 继承:继承父类的属性和方法 super:这个就是继承父类的代码的方法 重写:子类方法与父类方法同名,包含父类该方法的功能,用super 重载:子类完全重写父类同名方法,并且舍弃父类该方法的功能,不用super */ //创建一个父类 class Person{ constructor(name,sex){ this.name = name; this.sex = sex; } say(){ console.log(`${this.name}说:我是个${this.sex}人`) } } let p1=new Person('lan','男'); p1.say(); //lan说:我是个男人 //创建一个子类,继承父类 class Teacher extends Person{ constructor(name,sex,job){ super(name,sex); this.job=job; } say(){ super.say(); //同时调用父类该方法,表示重写,否则重载 console.log(`我的工作是${this.job}`) } teach(){ console.log("同学们,开始上课"); } } let p2=new Teacher('ling','女','语文老师'); p2.say();//line1: ling说:我是个女人 line2:我的工作是语文老师
原型关系:
class都有显示原型prototype和隐式原型_proto_
实例都有隐式原型_proto_
实例的_proto_指向创建该实例者的prototype
基于原型的执行规则:先在自身属性和方法寻找,找不到则自动去_proto_里寻找
原型链概述:实例→子类→父类→object,自身的隐式原型_proto_等于上一级的显示原型prototype,object是顶级对象,object的_proto_为null
四、同步和异步
概述:基于js是单线程语言,异步不会阻塞代码执行,同步会阻塞代码执行
前端异步应用场景:网络请求和定时任务
Promise基础用法:
function loadFun(url){ return new Promise((resolve,reject)=>{ /* 此处省略具体操作,一般结合传入的参数做处理 */ if(true){ resolve({data:'成功'}) }else{ reject({data:'失败'}) } }) } loadFun("参数").then(data=>{ console.log(data); //可以继续返回到下一个then函数里 return data; //返回一个普通对象 }).then(data=>{ //这里的data就是上面传下来的普通对象 if(data.data === '成功'){ console.log('执行成功'); } //then里面也可以继续调用promise方法,解决回调地狱问题 return loadFun("参数2") //返回一个promise实例 }).then(newData=>{ //这里就是接收的上面那个参数2的promise实例里返回的resolve对象 console.log(newData) }).catch(err=>{ //如果是reject返回的,就会在catch执行 console.log('执行失败') })