环境准备
构建:通过webpack babel把es6等转换为es5,让浏览器能识别
node开发环境 gitBash
vsCode插件
Beautify 代码格式化
ESLint 检查
作用域
全局作用域
var a=123 定义变量,不可以被删除
a=123 定义window的属性 可以delete,delete a 返回 true(隐式全局变量)
函数作用域
块状作用域 let const { let a=1 } 不可以通过window.a访问(全局对象的属性)
动态作用域 test.bind({a:100})() 转变test的this指向
词法作用域
ES5数组遍历
for循环
arr.forEach() : 不支持break和continue
arr.every() : 默认return false 需要return true才能接着循环遍历;也可以通过return false代替break中断循环
for in : 为对象设置 ,支持break和continue , 可以设置arr.a=0 数组的下标不应该是字符串 ,是for in 的瑕疵
ES6数组遍历
为遍历自定义数据结构:
const Price={
A:[1.5,2.3,4.5],
B:[3,4,5],
C:[0.5,0.8,1.2]
}
for of
Array.from(arrayLike.mapFn,thisArg
伪数组:按照索引存储数据,有length属性,只能foreach和for遍历
集合调用不了数组的API
ES6已经废弃arguments
ES5: let imgs=[].slice.call(document.querySelectorAll(‘img’))
ES6: let imgs=Array.from(document.querySelectorAll(‘img’))
新生成数组
let arr=Array.from({length:5},function(){ return 1})
let array=Array.of(1,2,3,4,5)
let array=Array(5).fill(7) //array.fill(8,2,4)) array.fill(value,start,end)
Array.from(‘foo’)
Array.from([1,2,3],x=x+x))
filter和find
filter 返回符合的所有的值的数组
find 返回符合的第一个值
findIndex 返回符合的第一个值的下标
类
修改原型链的方法
Animal.prototype.eat=function(){}
let monkey=new Animal()
monkey.constructor.prototype.eat=function(){} //改eat一起改
ES6:
class Animal{ constructor(type){ this.type=type } get age(){ return _age } //只读 set age(val){ if(val<7 && val>4){ _age=val } //写,可以做拦截 eat(){ console.log('eat food') } }
静态方法属于定义的类,拿不到当前的实例对象
实现继承
let dog=function(){
Animal.call(this,‘dog’)
}
dog.prototype=Animal.prototype
ES6:
class Dog extends Animal{
constructor(type){
super(‘dog’)
this.age=2
}
}
Default Parameters 函数默认值
function f(a,y=7,z=x+y){
console.log(f.length) // 定义时不是默认值的参数
return x10+z
}
Rest Parameter
function sum(base,…nums){
let num=0
nums.forEach(function(item){
num+=item1
}
return base*2+num
}
console.log(sum(1,2,3))
Spread Oprator
function sum(x=1,y=2,z=3){
return x+y+z
}
let data=[4,5,9]
console.log(sum(…data))
箭头函数
let hello=name=>{
console.log(‘hello’,name)
}
只有一个参数并且不是对象,可省略()
箭头函数=>后面的表达式就是返回值
如果返回值是对象,不可以省略{}
Object Property
键值对简写
键可以是表达式,用【】括起来:[x+y]:6
Set数据结构
let s=new Set()
s.add(‘hello’).add(‘bye’).add(‘hello’) //会过滤重复数据
s.clear()
s.has(‘hello’)
s.size
s.keys() s.values()
s.entries() //拿到所有键值对
Map数据结构
Map键值可以是任意值,Map和Set都是可以遍历的
let map = new Map()
let map=new Map([[1,2],[2,3]] //1是键,2是值
map.set(1,2) //可以添加和修改
map.delete(1) //删除索引1的数据
map.clear()
map.size
map.has(1) //按索引值查找
map.get(1)
map.keys() map.values() map.entries()
for(let [key,value] of map){}
Object.assign
Object.assign(target,source) //浅拷贝 如果是对象,拷贝的是地址
Regexp Sticky修饰符(y修饰符)
let s=‘aaa_aa_a’
r1=/a+/g
r2=/a+/y //粘连,只能第一个匹配连续匹配
r1.exec(s) //aaa
r2.exec(s) //aa
r1.exec(s) //4
r2.exec(s) //null
RegExp Updates(u修饰符)
当一个字符
字符串有中文,要加u
`javascript
let s=‘告’
let s2 = ’ \ uD842\uDFB7 ’
console. log( /^\uD842/. test(s2))
console. log( /^\uD842/u. test(s2))
^起始 $结束
**判断**
多个判断,两种简便方法
```javascript
var flag= c!==a && c!==b
if(![a,b].includes(c)){} //includes可以用在数组和字符串
if(flag)
模板字符串
const str=my age is ${a+b} i love ${c}
可以处理换行
let s1=`我是第一行
我是第二行`
函数,包含逻辑运算
function Price(strings,type){
let s1=strings[0]
const retailPrice=20
const wholeSailePrice=16
let showTxt
if(type==='retail'){
showTxt='购买单价是:'+retailPrice
}else{
showTxt='购买的批发价是'+wholeSalePrice
}
return `${s1}${showTxt}`
}
let showTxt=Price`您此次的${retail}`
console.log(showTxt)
Array Destructure 数组解构赋值
let [firstName,lastName]=arr
let [first,last]=new Set([1,2,3,4])
let user={name:‘s’,surname:‘t’};
[user.name,user.surname]=[1,2]
let user={name:‘s’,surname:‘t’} //循环体赋值
for(let [k,v] of Object.entrier(user)){ //把user变成可遍历
}
let [first=‘hello’,last,…last]=arr //让别的不被使用的数据不被回收,给first做默认值赋值
Object Destructor对象解构赋值
let options={
title:'menu',
width:100,
height:200
}
let {title:title2,width,height,radiu=2}=options
console.log(title2,width,height)
嵌套:左右结构要一致
let options={
size:{
width:200
height:100
}
item:['Cake','Dount'],
extra:true
}
let {size:{width:width2,height},items:[,item2],extra}=options
Callback(异步操作)
回调地狱:a回调b,b回调c
function loadScript(src,callback){
let script=document.creatElement('script')
script.src=src
script.onload=()=>{callback(src)}
script.onerr=(err)=>{callback(err)}
document.head.append(script)
}
function test(){
console.log('test')
}
loadScript('./1.js,test)
Promise
//pending->fulfilled/reject (状态转变不可逆)
//promise.then(onFulfilled,onRejected) 这两个参数都是方法
//.then返回一个新的Promise对象,因此可以链式调用原型上的then方法
function loadScript(src){
//pending,undefined
return new Promise((resolve,reject)=>{
let script=document.creatElement('script')
script.src=src
script.onload=()=>resolve(src) //fulfilled,result
script.onerror=(err)=>reject(err)//rejected,error
document.head.append(script)
})
}
loadScript('./1.js')
.then(()=>{
return loadScript('./4.js') //不加return,就算报错也会执行3.js
},(err)=>{
console.log(err)
})
.then(()=>{
loadScript('./3.js')
},(err)=>{
console.log(err)
})
Resolved/Rejected
通过resolve(10)传入一个数值,执行.then()
function test(bool){
if(bool){
return new Promise((resolve,reject)=>{
resolve(30)
})
}else{
return Promise.reject(new Error('ss'))
// return Promise.resolve(10)
}
}
test(0).then((value))=>{
console.log(value)
},(err)=>{
console.log(err)
})
Catch(异步操作)
loadScript('./1.js')
.then(()=>{
return loadScript('./4.js')
})
.then(()=>{
return loadScript('./3.js')
})
.catch(err=>{
console.log(err)
})
All(异步操作)
全到
const p1=Promise.resolve(1)
const p2=Promise.resolve(2)
const p3=Promise.resolve(3)
Promise.all([p1,p2,p3]).then((value)=>{
console.log(value)
})
Race(异步操作)
先到先得
const p1=()=>{
return Promise((resolve,reject)=>{
setTimeout(function(){
resolve(1)
},3000)
})
}
const p2=()=>{
reutrn Promise(resolve,reject)=>{
setTimeout(function(){
resolve(2)
},0)
}
}
Promise.race([p1(),p2()]).then((value)=>{
console.log(value)
})
finally
const Gen =(time)=>{
return new Promise((resolve,reject)=>{
setTimeout(function(){
if(time<500){
reject(time)
}else{
resolve(time)
}
},time)
})
}
Gen(Math.random()*1000)
.then(val=>console.log('resolve',val))
.catch(err=>console.log('reject',err))
.finally(()=>{console.log('finish')})
反射机制
Reflect.apply
console.log(Reflect.apply(Math,null,[4.72]))
//console.log(Math.floor.apply(null,[4.72])
console.log(Reflect.apply(price>100?Math.floor:Math.ceil,null,[price]))
Reflect.construct
let d=Reflect.construct(Date,[]) //相当于new
console.log(d.getTime())
//增加值
const student={}
const r=Reflect.defineProperty(student,'name',{value:'Mike2'} // r是true
//const r=Object.defineProperty(student,'name',{value:'Mike2'} r是修改后的student
//删除值
const obj={x:1,y:2}
console.log(Reflect.delete(obj,'x')
//获取值
Reflect.get(obj,'x')
Reflect.get([3,4],1)
Reflect.getOwnPropertyDescriptor(obj,'y')) //看他的值,是否可扩展等
Reflect.getPrototypeOf(d) //看原型上的方法
Reflect.has(obj,'x') //验证对象上有没有属性 Object没有这个方法
Reflect.isExtensible(obj) //验证是否可拓展 如果Object.freeze(obj)/preventExtensions(obj)之后 , 这个方法返回false
Reflect.ownKeys(obj) //返回对象的值
Reflect.set(obj,'z',4) //赋值操作,写
Reflect.setPrototypeOf(arr,String.prototype) //修改原型对象
Proxy代理
https://blog.csdn.net/weixin_45195200/article/details/100113005
//中介排序
let o={
name:'Xiaoming',
price:190
}
let d=new Proxy(o,{
get(target,key){
if(key==='price'){
return target[key]+20
}else{
return target[key]
}
}
})
console.log(d.price,d.name)
//拦截修改,用户拦截
let d= new Proxy(o,{
get(){}
set(target,key,value){
return false
}
}
//es5 Object.defineProperty(o,key,{writable:false})
//可撤销
let d=Proxy.revocable(o,{})
d.revoke() //撤销
//监听错误,上报
window.addEventListener('error',(e)=>{
console.log(e.message)
report('./')
},true)
//校验规则
let validate=(target,key,value)=>{
if(Reflect.has(target,key)){
if(key==='price'){
if(value>300){
throw new TypeError('price exceed 300')
}else{
target[key]=value
}
}else{
target[key]=value
}
}else{
return false
}
}
let d=new Proxy(o,{
get(target,key){
return target[key]||''
},
set:validator
})
//2
class Component {
constructor () {
this.proxy = new Proxy({
id:Math.random().toString(36).slice(-8)
}, {})
}
get id(){
return this.proxy.id
}
}
let com = new Component( )
let com2 = new Component( )
for(let i=0;i<10;i++){
console. log(com. id, com2. id)
}
Generator函数
function * gen () {
let val
val=yield * [1,2,3]
console. log(val)
}
console. log(l.next())
//next返回遍历和done:true/false
g.throw(new Error('ss')//抛出异常
g.return()
场景模拟 抽奖
依次输出第一二三等奖,并保证不重复
while(1){
if(count<first){
random = Math.floor(Math.random()*firstPrise.length)
yield firstPrise[random]
firstPrice.splice(random,1)
}else if{ count<first+second){
random=Math.floor(Math.random()*secondPrise.length)
yield secondPrise[random]
second.splice(random,1)
}else if(count<first+second+third){
random=Math.floor(Math.random()*thirdPrise.length)
yield thirdPrise[random]
}else{
return false
}
}
console.log(dom().next().value())
Iterator迭代器
自定义遍历
需要有iterator,有next()函数next里面有{done value}
let authors = {
allAuthors: {
fiction: [ 'Agla','Skks','LP'],
scienceFiction: [ 'Neal', 'Arthru', 'Ribert'],
fantasy: ['J.R.Tole', 'J.M.R', 'Terry P.K']
},
Address: []
}
//遍历器接口
authors[Symbol.iterator]=function(){
let allAuthors=this.allAuthors
let keys = Reflect.ownKeys(allAuthors)
let values=[]
return{
next(){
if(!values.length){
if(keys.length){
values=allAuthors[keys[0]]
keys.shift()
}
}
return {
done:!values.length, //说明遍历是否结束
value:values.shift() //遍历得到的值
}
}
}
}
let r=[]
for(let v of authors){
r.push(v)
}
console.log(r)
Export Import 模块化
export default 默认导出,只能一个
import name2 from ‘’ 可以重新起名字
import {addr as arr2} from’’ 不是默认变量的话可以重新起名字
export default{data,des}
import obj from ‘’
let {data,des}=data
export classText{}
export default class text{}
import * as Mod from ‘’
let people = new Mod.default()
console.log(people.id)
include +pow
2 ** 5 / Math.pow(2,5)
arr.includes(4)
Async_Await
async返回一个promise对象,对象状态是resolved
await 只能在async中用,返回promise 传入的不是promise 的话,会自动转化伪promise.resolved()
快速遍历Object.keys.values.entries
Object.keys(grade).filter(item=>item===‘lilei’)
Object.values(grades).filter(item=>item>96)
for(let [k,v] of Object.entries(grade)){}
String Padding 字符串补白
for(let i=1;i<32000;i++){
console.log(i.toString().padStart(5,’*#’) //往后补:padEnd
}
Object.getOwnDescriptor描述符
对数据的操作 enmurable/writable
**for await of **
异步迭代器 Async Iterrator
使用Symbol.asyncIterator作为key
异步迭代器必须返回promise对象 且Promise 返回{value,done}
搭配使用for- await -of
// function Gen(time){
// return new Promise((resolve,reject)=>{
// setTimeout(function(){
// resolve(time)
// },time)
// })
// }
// async function test(){
// let arr=[Gen(2000),Gen(100),Gen(3000)]
// for await (let item of arr){
// console.log(Date.now(),item)
// }
// }
// test()
const obj ={
count:0,
Gen(time){
return new Promise((resolve,reject)=>{
setTimeout(function(){
resolve({done:false,value:time})
},time)
})
},
[Symbol.asyncIterator](){
let self=this
return{
next(){
self.count++
if(self.count<4){
return Gen(Math.random()*1000)
}else{
return Promise.resolve({
done:true,
value:''
})
}
}
}
}
}
async function test(){
for await(let item of obj){
console.log(Date.now(),item)
}
}
正则
//dotAll
//.匹配任意字符,但是不匹配换行符之类,可以用dotAll 后面加s
console.log(/foo.bar)/us.test('foo\nbar') //u是匹配中文字符
console.log(re.dotAll) //判断re是否用了dotAll 或者 re.flags
//命名分组匹配
const t='2019-06-07'.match(/(?<year>\d{4})-(?<month>\d{2}-(?<day>\d{2}))
console.log(t.groups.year)
//先行|后行断言
//先遇到一个条件再接着判断:先行断言
let test='hello world'
console.log(test.match(hello(?=/sworld)/))
//遇到往前走:后行断言
console.log(test.match(/(?<=hello\s)world/)
ES10新增
console.log(JSON.stringify('\u{D800}')) //JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串。
let arr=[1,[2,3],[4,5,[6,7]]]
console.log(arr.flat(3)) //arr.flat(depth)
arr.flatMap(item=>[item*2])
str.trimStart()/str.trimLeft() //去除首部空格
str.trimRight()/str.trimEnd() //去除尾部空格
str.trim()//
str.matchAll(regExp) //匹配所有结果
const arr=[['foo',1],['bar',2]]
const obj=Object.fromEntries(arr) //Object.fromEntries() 方法把键值对列表转换为一个对象。
console.log(obj)
const obj={
abc:1,
def:2,
ghs:3
}
let res=Object.fromEntries(
Object.entries(obj).filter(([key,val])=>key.length===3)//转化为数组,可以调用数组的api,Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组
)
console.log(res)
vue
vue指令
import Vue from 'vue
Vue.directive('make-res',{
inserts:(el){
el.style.color='red'
}
}
代理配置
module. exports = {
devServer: {
proxy: {
' /user': {
target: ' http:// localhost :8081' ,
pathRewrite: {
' /user': 'user. json'
}
},
' /list': {
target: ' http:// localhost:8081',
pathRewrite: {
'/list': 'list. json'
}
}
}
}
}
解构赋值
async mounted(){
count{data:{list}}=await axios.get('/list')
this.$data.list=list
}
}
navigator.language
代理proxy
methods:{
up (){ this.price=this.proxy.up},
down(){this.price=this.proxy.down},
reset (){this.price=this.proxy.default}
}
async mounted (){
const {data:{price}}=await axios.get('./proxy')
Object.freeze(prize)
this.proxy=new Proxy({},{
get(target,key){
if(key === 'up'){
return [].concat(price).sort((a,b)=>a-b)
}else if(key === 'down'){
return [].concat(price).sort((a,b)=>b-a)
}else{
return price
}
},
set (){
return false
}
})
this.price=this.proxy.default
}
自定义遍历
async mounted (){
const{data:{allAuthors}}=await axios.get('./author')
const author=new Proxy(allAuthors,{
has(target,key){
const keys=Reflect.ownKeys(target).slice(0,-2)
for(const item of keys){
if(target[item].includes(key)){
return true
}
}
return false
}
})
author[Symbol.iterator]=function *(){
const all=this
const keys=Reflect.ownKeys(this).slice(0,-2)
let values=[]
while(1){
if(!values.length){
if(keys.length){
values=[].concat(all[key[0]])
keys.shift()
yield values.shift()
}else{
yield values.shift()
}
}
}
}
this.authors=allAuthors
}
webpack
本质上, webpack是-个现代JavaScript 应用程序的静态模块打包工具。当webpack处理应用程序时,它会在内部构建一个依赖图(dependency graph),此依赖图会映射项目所需的每个模块,并生成一个或多个bundle。
const path=require(‘path’);
module.exports={
entry:’./…js’
output:{
path:path.resolve(_dirname,‘dist’),
filename:’./.js’
}
modules:{
rules:[
{test:/.txt$/,use:‘raw-loader’}
]
}
plugin:[
new HtmlWebpackPlugin({template:’./.html’})
]
mode:‘production’
}
babel
1.代码解析:相同功能不同语法
2.抽象语法树
3.转换成es5语法树
4.增删代码
5.还原代码(index.min.js)
ESlint
代码检查并格式化
依赖规则,如:Variables规则
每个规则会设置三个检查等级:
●"off"或0-关闭规则
●"warn"或1 -开启规则,使用警告级别的错误: warn (不会导致程序退出)
●"error"或2 -开启规则,使用错误级别的错误: error (当被触发的时候,程序会退出)
eslint:
eslintrc.json
ES6补充
function a (a=2,b=3){
}
a(undefined,5)
避免输入框攻击
function sanitize(string,…values){
const dirty=strings.reduce((prev,curr,i)=>${prev}${curr}${values[i]||''|
,’’);
return DOMPurify.sanitize(dirty);
}
commentDiv.innerHTML=santize`
循环遍历
for循环,较繁琐
forEach,不支持continue/break
for in ,遍历所有可枚举的值的键,包括属性
for of,得到对象的值
Array.from
function sum(){
return Array.from(arguments).reduce((prec,curr)=>prev+curr,0)
}
Array.of创建固定数组
Array.of(1) //1
回调地狱
Promise axios是promise的
function getReoBuid(id){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
const repo=repos.find(repo => repo.id ===id);
if(repo){
resolve(repo)
}else{
reject(error('no repo'))
}
},2000)
})
}
function conboundOwner(repo){
return new Promise((resolve,reject)=>{
const owner=owners.find(owner=>owner.name===repo.name)
if(owner){
resolve(owner)
}else{
reject(error('no owner'))
}
})
}
getReoBuid(1)
.then(repo=>{
return conboundOwner(repo)
})
.then(repo=>{
console.log(repo)
})
.catch(error=>{
console.error(err)
})
symbol
[Symbol(‘lili’)]:{grade:60,gender:‘male’}
const syms=Object.getOwnPropertySymbol(classRoom).map(sym=>classRoom.sym)
webpack
package.json:
“scripts”:“webpack --progress --watch”
–progress:说明进度 --watch变化
生成用户头像:gravatr
SystemJS
package.json:
“server”:“webpack --progress --watch”
babel
babel-polify : 新增的方法
公用方法:不会每新成一个对象的时候都新生成一个方法:prototype…
let methodName=‘info’;
class User{
constructor(name,email){
this.namee=name;
this.age=age;
}
methodName{}
set github(value){this.gitHub=gutHub}
get gitHub(){return `https://hitHub.com/${this.github}’
}
typeof User:function
static descript(){} 只能在类User上调用,不能在实例上调用
箭头函数不能用auguments
console.table()
排序:this.sort((a,b)=>{a.score>b.score)?-1:1).slice(0,limit)
WeakSet只能是对象
set()
map()
异步
ajax请求
setTimeout(alert是同步,会阻塞)
事件绑定
单线程:一次只能干一件事,遇到异步函数,先暂存起来
日期
var dt=bew Date()
dt.getTime() //获取毫秒数
dt.getFullYear()
dt.getMonth()
dt.getDate()
dt.getHours()
dt.getSeconds()
Math.random() //获取0-1的随机数
forEach() //遍历元素
every()
some()
sort()
map() //对元素重新组装
filter()
遍历对象
var obj={
name:'lily',
age:10,
height:150
}
for(let key in obj){
if(obj.hasOwnProperty(key){
cosole.log(key,obj[key])
}
}