{} // 塊級作用域
for if while // 都是塊級作用域
沒有預解析,不存在變數提升
在程式碼塊內,只要let定義變數,在之前使用報錯(先定義,再使用)
function show(){
console.log(a);
let a = 3; //報錯
}
不能重複定義變數(同一個作用域)
for回圈for回圈裏面是父級作用域,裏面又一個作用域
for(let i=0;i<3;i++){ // 兩個作用域
let i= 'abc';
console.log(i);
// abc abc abc
}
暫時性死區
const 特性和let一樣
const 常數不能修改 const定義完變數,必須有值,不能後賦值
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
if (true) {
// TDZ開始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ結束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
物件參照可以修改 例如:
const arr = [1,2,2];
arr.push(3);
// 1,2,2,3
Object.freeze([1,2,3]) //不能修改
(function(){
})() //用來模擬作用域
注意:左右兩邊,結構保持一致
let [a,b,c] = [12,5,6];
let [a='預設值',b,c] = [12,5];
let [a,b,c:'預設值'] = [12,5,null]; c = null
let a= 12;
let b= 5;
[a,b] = [b,a]; a = 5,b = 12
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
json 物件結構
let json = {
name: 'xxx',
age: 18
}
let {name,age} = json;
console.log(name,age);// xxx 18
let {name:n,age} = json; //n別名
let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"
let { baz } = { foo: 'aaa', bar: 'bbb' };
baz // undefined
如果變數名與屬性名不一致,必須寫成下面 下麪這樣。
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'
let obj = {
p: [
'Hello',
{ y: 'World' }
]
};
let { p, p: [x, { y }] } = obj;
x // "Hello"
y // "World"
p // ["Hello", {y: "World"}]
字串的解構賦值 解析時候可以給預設值 傳參也可以結構
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
let {length : len} = 'hello';
len // 5
優點:隨意換行
`${}`
let name = 'xxx';
let age = 18;
let str = `這個人叫${name},年齡是${age}`
字串方法 查詢
indexOf('') // 返回索引位置
str.includes(要找的東西) //返回true/false
str.startswith() // 以xxx開頭
str.endswith() // 以xxx結尾
str.repeat(n) // 重複多少次
str.padStart(整個字元常長度,填充的東西) // 往前填充
str.padEnd() //往後填充
函數預設參數
function show(x='預設值',y='預設值'){
console.log(x,y);
};
show('','a');
show('b');
*結構
function show({x=0,0}={}){
console.log(x,y);
};
show({x:1,y:7});
show();
函數參數預設已經定義,不能再使用let,const宣告
function show(x=18){
let x=101; //報錯
}
show();
擴充套件運算子 Rest運算子 … //擴充套件運算子
即展開又可以重置
展開陣列
let arr = [1,2,3];
console.log(arr); //[1,2,3];
console.log(...arr);
// 1,2,3
合併
function show(...a){
console.log(a) //[1,2,3,4,5]
}
show(1,2,3,4,5)
類似
function show(){
let a = Array.prototype.slice.call(arguments);
console.log(a); // [1,4,5,2,9,4]
}
show(1,4,5,2,9,4);
剩餘運算子
展開陣列 [1,2,3]->…[1,2.3]->1,2,3 重置 1,2,3-> …1,2,3 -> [1,2,3] 剩餘參數:必須放到參數最後
function show(a,b,...c){
// a = 1,
// b = 2,
// c= [3,4,5]
}
show(1,2,3,4,5)
let arr = [1,2,3];
let arr2 = [...arr]; // [1,2,3]
或者 let arrs = Array.from(arr); // [1,2,3]
let str = 'a b c'; let arrs = Array.from(str); // ['a','b','c']
箭頭函數
注意:
1.this問題,定義函數所在的物件,不再是執行時所在的物件
2.箭頭函數沒有arguments,用…
3.箭頭函數不能當建構函式
let show = () => 1;
console.log(show()); // 1
() => {
語句
}
let show = (a=12,b=8)=>{
console.log(a);
return a*b;
}
let json = {
id: 1,
show:function(){
alert(this.id); // 1
}
}
json.show();
let json = {
id: 1,
show:function(){
setTimeout(function(){
alert(this.id); // undefined
},200)
//setTimeout是用window執行的,
window沒有id
}
}
json.show();
var id = 10;
let id = 10; //如果是let定義也是undefined
let json = {
id: 1,
show:function(){
setTimeout(function(){
alert(this.id); // 10
},200)
}
}
json.show();
let json = {
id: 1,
show:function(){
setTimeout(()=>{
alert(this.id); // 1
},200)
}
}
json.show();
var id= 6;
let json = {
id: 1,
show:function(){
setTimeout(()=>{
let id = 10;
alert(this.id); // 1
},200)
}
}
json.show();
var id= 6;
let json = {
id: 1,
show:()=>{
alert(this.id) // 6
setTimeout(()=>{
let id = 10;
alert(this.id); // 6
},200)
}
}
json.show();
let id= 6;
let json = {
id: 1,
show:()=>{
alert(this.id) //undefined
setTimeout(()=>{
let id = 10;
alert(this.id); // undefined
},200)
}
}
json.show();
for回圈 2.while
/ /es5新增
(forEach,map,filter,some,every,reduce,reduceRight)
arr.forEach()
// 以下他們可以接受兩個參數(回圈回撥函數,this指向誰)
let arr=[1,2,3];
for(let i = 0;i < arr.length; i++){
}
arr.forEach()//代替普通for回圈
arr.forEach(function(val,index,arr){
console.log(this)//456 this指向456
},456);
// 箭頭形式
arr.forEach((val,index,arr)=>{
console.log(this)// this指向window
},123);
// 箭頭函數this指向定義時 window
arr.map()
非常有用,做數據互動,‘對映’ 正常情況下,需要配合return,返回是一個新陣列,如果沒有return,相當於forEach 注意:平時用map,一定要有return;
let newArr = arr.map((item,index,arr)=>{
return item;
});
newArr = [1,2,3];
arr.filter()
let arr = [{title:'111',hot: false},
{title: '222',hot:true},{title:'333',hot:false}]
let newArr = arr.filter((item,index,arr){
return item.hot === true;
});
console.log(newArr);
// [{title: '222',hot:true}]
arr.some()
類似查詢,數組裏面某一個元素符合,返回true //過濾 過濾一些不合格,如果回撥函數返回true,就留下來
let arr = ['aa','bb','cc'];
let back = arr.some((item,index,arr)=>{
return item === 'aa'
});
console.log(back)//true
arr.every()
數組裏面所有的元素都要符合條件,才返回true
arr.reduce()
從左往右 //求陣列的和,階乘 接收的參數與其他不同
let arr = [1,2,3,4,5,6,7,8,9,10];
let res = arr.reduce((prev,cur,index,arr)=>{
return prev+cur;
});
// 55 prev上一個結果,cur當前值
arr.reduceRight() //從右往左
// for----of
let arr = ['aaa','bbb','ccc'];
for(let val of arr){
console.log(val) //
aaa bbb ccc
}
for(let index of arr.keys()){
console.log(index) //
0 1 2
}
for(let item of arr.entries()){
console.log(item) //
[0,'aaa'] item[0] 1 item[1] aaa
[1,'bbb']
[2,'ccc']
}
for(let [key,val] of arr.entries()){
console.log(key,val);//
0 aaa
1 bbb
2 ccc
}
Array.from()
作用:把類陣列(獲取一組元素,arguments…)物件轉成陣列 個人觀點:具備length這東西就靠譜
[].slice.call(arr) //ES5之前的方法 Array.from(arr)//ES6方法 [...arr]//ES6方法
let str = "stri";
Array.from(str) // ['s','t','r','i'];
let json = {
0:'aa',
1: 'bb',
2: 'cc'
}
Array.from(json) //不行
let json = {
0:'aa',
1: 'bb',
2: 'cc',
length: 3
}
Array.from(json) // ['aa','bb','cc']
let json = {
0:'aa',
1: 'bb',
2: 'cc',
length: 2
}
Array.from(json) // ['aa','bb']
Array.of()
把一組值轉成陣列
Array.of('aa','bb')
// ['aa','bb']
arr.find()
查詢找出第一個符合條件的陣列成員,如果沒有找到,返回undefined
let arr = [23,59,900,200];
let res = arr.find((val,index,arr)=>{
return val > 100; // 900
});
arr.findIndex()
找的是位置,沒找到返回-
let arr = [23,59,900,200];
let res = arr.find((val,index,arr)=>{
return val > 100; // 2
});
arr.fill(填充的東西,開始位置,結束位置)
let arr = new Array(10);
arr.fill('預設值')
['預設值',...]
arr.includes()
在ES2016裏面新增 類似 arr.indexOf()返回索引
let arr = [1,2,3];
arr.includes(1) // true
let a=new Set([1,2,3]);
let b=new Set([4,3,2]);
//交集
let union= [...new Set([...a,...b])];
console.log(union);
//並集
let intersect= [...new Set([...a].filter(x=> b.has(x)))];
console.log(intersect);
//差集
let difference= [...new Set([...a].filter(x=> !b.has(x)))];
console.log(difference);
物件
let name='aaa';
let json={
name,
show(){//個人建議,一定注意,不要箭頭函數
return this.name //'aaa'
}
}
let name='aaa';
let json={
name,
show()=>{//個人建議,一定注意,不要箭頭函數
return this.name //沒值
}
}
Object.is()
用來比較兩個值是否相等
console.log(Object.is(NaN,NaN)//true
console.log(+0 == -0)//true
console.log(Object.is(+0,-0))//false
Object.assign(目標物件,source1,source2)
1.用來合併物件 用途: 1.複製一個物件 2.合併參數
let json = {a:1};
let json2 = {b:2};
let json3 = {c:3};
Object.assign({},json,json2,json3);
// {a:1,b:2,c:3}
let json4 = {b:2,a:2};
Object.assign({},json4,json3);
//{a:2,b:2,c:3}
//2.
let arr = ['aa','bb','cc'];
Object.assign([],arr);
//['aa','bb','cc']
Object.keys()
Object.values()
Object.entries()
let json = {
a:1,
b:2,
c:3
}
for(let key of Object.keys(json)){
console.log(key) // a b c
}
for(let value of Object.values(json)){
console.log(value) // 1 2 3
}
//或者這麼寫 解構
let {keys,values,entries} = Object;
for(let item of entries(json)){
console.log(item)
// ['a':1] ['b':2] ['c':3]
}
for(let [key,value] of entries(json)){
}
物件身上:計劃ES2018引入 … 擴充套件複製等
let {x,y,...z} = {x:1,y:2,a:3,b:4}
// x:1
y:2
{a:3,b:4}
let json = {a:3,b:4};
let json2 = {...json};
// a:3 b:4
作用:解決非同步問題
傳統方式,大部分用回撥函數,事件
ajax(url,{ //獲取token
ajax(url,{ //獲取使用者資訊
.... //獲取使用者相關資訊
})
})
語法
let promise = new Promise(function(resolve,reject){
// resolve 成功呼叫
// reject 失敗呼叫
});
promise.then(res=>{
},err=>{
});
promise.catch(err=>{//reject,發生錯誤別名
console.log(err)
});
或者
promise.then(res=>{
}).catch(err=>{
});
let a = 10;
let promise = new Promise((resolve,reject){
if(a===10){
resolve('成功')
}else{
reject('失敗')
}
});
promise.then(res=>{
console.log(res);
},err=>{
console.log(res);
});
Promise.resolve(‘aa’):將現有的東西,轉成一個Promise物件,resolve狀態,成功狀 態
Promise.reject(‘bb’):將現有的東西,轉成一個Promise物件,reject狀態,失敗狀態
let p = Promise.resolve('aa');
p.then(resolve=>{
resolve('aaa')
})
Promise.all([p1,p2,p3]);
把Promise打包,扔到數組裏面,打包完還是一個 Promise物件必須確 保,所有的promise物件,都是resolve狀態,都是成功的狀態
let p1= Promise.resolve('aaa');
let p2 = Promise.resolve('bbb');
let p3= Promise.resolve('ccc');
Promise.all([p1,p2,p3]).then(res=>{
let [res1,res2,res3] = res;
console.log(res1,res2,res3)
})
Promise.race([p1,p2,p3]);
只要有一個resolve,就返回
let p1= Promise.reject('aaa');
let p2 = Promise.reject('bbb');
let p3= Promise.resolve('ccc');
Promise.all([p1,p2,p3]).then(res=>{
let [res1,res2,res3] = res;
console.log(res1,res2,res3)
}).catch(res=>{
});
使用者登錄->使用者資訊
let status = 1;
let userLogin = (resolve,reject)=>{
setTimeout(()=>{
if(status ===1){
resolve({data:'登錄成功,age:xx})
}else{
reject('失敗')
}
},2000)
}
let getUserInfo = (resolve,reject)=>{
setTimeout(()=>{
if(status ===1){
resolve({data:'獲取使用者資訊,age:xx})
}else{
reject('失敗')
}
},1000)
}
new Promise(userLogin).then(res=>{
console.log('使用者登錄成功');
console.log(res);
return new Promise(getUserInfo);
}).then(res=>{
console.log('獲取使用者資訊成功')
console.log(res);
})
//使用者登錄成功
// {data: xxx}
// 獲取使用者資訊成功
// {data: '獲取使用者資訊'}
js不支援模組化 在ES6之前,社羣制定一套模組規範 Common.js 主要伺服器端
node.js require(‘http’) AMD requireJs ,curlJs ,seaJs
ES6出來,同意伺服器端和用戶端模組規範 import {xxx} ddd;
使用模組( 注意放到伺服器環境 )
1.如何定義模組 export const a = 1;
2.如何使用 import ‘./module/1.js’
<script type ="module">
import './module/1.js'
</script>
1.js
console.log('模組載入了')
export const a = 1;
或者
const a = 1;
const b = 2;
export {
a,
b as c // 別名
}
import特點 :可以是相對路徑,也開始絕對路徑
import {a as x, c} from './module/1.js';
import 模組只會匯入一次,無論引入多少次
<script type ="module">
import {a as x, c} from './module/1.js';
console.log(x,c) //
//模組載入了
1 2
import * as mode from './module/1.js';
mode.a // 1
</script>
exprot default a = 12; // 不用{}需要定義default
import a from './module/2.js';
a // 12
3.js
const a= 12;
const b = 5;
或者import {a,b} from './module/1.js';
const sum = ()=>{
return a+b;
}
const show = ()=>{
return 'aaa'
}
class Person {
constructor(name,age){
this.name = name;
this.age = age;
}
showName(){
return this.name;
}
}
export {
a,b,sum,show
}
export default {
Person
}
console.log(a,b) // 12 5 // 有提升效果
import mode,{show,sum,a,b} from './module/3.js';
let p = new node.Person('xx');
show(); //aaa
sum(); // 17
console.log(a,b) // 12 5
p.showName() // xx
import() 例子
let a = 12;
if(a===12){
import {a} from './module/1.js';
}else{
import {b} from './module/2.js';
}
// 錯誤的
import('./module/1.js').then(res=>{
console.log(res.a) // 12
})
返回值是個Promise物件
優點:
1.按需載入
2.可以寫if中
3.路徑也可以動態
Promise.all()
Promise.all(['./1.js','./2.js']).then([mode1,mode2])=>{
})
ES2017 加 async wait
async function main(){
const mode1 = wait import('./1.js');
const mode2 = wait import('./1.js');
const [m1,m2] = wait Promise.all([mode1,mode2]).then([import('./1.js'),import('./2.js')]);
console.log(m1,m2);
}
main();
‘use strict’ 嚴格模式
ES5之前是通過函數模擬
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.showName = function(){
return this.name;
}
或者
object.assign(Person.prototype,{
showName(){
return this.name;
},
showAge(){
return this.age;
}
});
let p = new Person('strive',18);
p.showName(); // strive
ES6寫法:
1.class沒有提升功能,沒有預解析,在ES5用函數模擬可以,預設函數提升
2.this比之前輕鬆多了
class Person{
//建構函式,呼叫new ,自動執行
constructor(name,age){
this.name = name;
this.age = age;
}
showName(){
return this.name;
}
}
new Person('strive',age);
或者這麼定義 不推薦使用
const Person = class{
//建構函式,呼叫new ,自動執行
constructor(name,age){
this.name = name;
this.age = age;
}
showName(){
return this.name;
}
}
let show = 'other';
let show1 = 'uuu';
const Person = class{
//建構函式,呼叫new ,自動執行
constructor(name,age){
this.name = name;
this.age = age;
}
showName(){
return this.name;
},
show(){
console.log('xxx');
},
[show1](){
console.log('yyy');
}
[show+show1](){
}
}
let p = new Person('strive',18);
p.show() // 'xxx'
p.show1() // undefined
p[show1]() // 'yyy'
矯正this
1.fn.call(this指向,arg1,arg2…)
2.fn.apply(this指向,[arg1,arg2…]);
3.fn.bind();
class Person{
constructor(){
this.name = 'strive';
this.showName = this.showName.bind(this);
}
showName(){
return this.name;
}
}
let p =new Person();
let {showName} = p;
console.log(showName())//報錯
可以用 this.showName = this.showName.bind(this); //矯正
class裏面取值函數(getter),賦值(setter)
class Person(){
constructor(){
}
get aaa(){
return `aaa的屬性`
}
set aaa(val){
console.log(val) //111
}
}
let p = new Person();
p.aaa = '111';
console.log(p.aaa)//111的屬性
靜態方法:就是類身上的方法
static fn(){}
靜態方法可以由子類繼承
class Person(){
constructor(){
}
showName(){
}
static show(){
return '這是靜態方法'
}
}
let p = new Person();
p.showName();
Person.show();
父類別子類 繼承之前的方法
//父類別
function Person(name){
this.name = name;
}
Person.prototype.showName = function(){
return this.name;
}
//子類
function Student(name,skill){
Person.call(this,name);//繼承屬性
this.skill = skill;
}
Student.prototype = new Person();//通過繼承方法
呼叫
let stu = new Student('strive','逃學');
stu.showName();
ES6繼承 extends
// 父類別
class Person(){
constructor(name){
this.name = name;
}
showName(){
console.log('父類別')
}
}
// 子類
class Student extends Person{
constructor(name,skill){
super(name);//父類別建構函式
this.skill = skill;
}
showName(){
super.showName()//父類別方法執行
console.log('子類')
}
show(){
console.log(this.name,this.skill)
}
}
let stu = new Student('xxx','yyy');
stu.skill // yyy
stu.show() // xxx yyy
stu.showName(); // 父類別 子類
拖拽
<div id="div1"></div>
<div id="div2"></div>
class Drag{
constructor(id){
this.oDiv = document.querySelector(id);
this.disX = 0;
this.disY = 0;
this.init();
}
init(){
this.oDiv.onmousedown = function(ev){
this.disX = ev.clientX - this.oDiv.offsetLeft;
this.dixY = ev.clientY - this.oDiv.offsetTop;
document.onmousemove = this.fnMove.bind(this);
document.onmouseup = this.fnUp.bind(this);
return false;
}.bind(this);
}
fnMove(ev){
this.oDiv.style.left = ev.clientX-this.disX +'px';
this.oDiv.style.top = ev.clientY-this.disY+'px';
}
fnUp(){
document.onmousemove = null;
document.onmouseuo = null;
}
}
//子類
class LimitDrag extends Drop{
fnMove(ev){
super.fnMove(ev);
//限制範圍
if(this.oDiv.offsetLeft <= 0){
this.oDiv.style.left = 0;
}
}
}
//new Drag('#div1'); //能拖出去
new LimitDrag('#div2');//限制拖出去
數據型別
// number string boolean Object undefined function
// 用typeof 檢測出來數據型別
Symbol
new Number(12)
Symbol使用一般
注意:
1、Symbol不能new
2、Symbol()返回是一個唯一值(房建傳說,做一個key,定義一些唯一或者私有)
3、Symbol是一個單獨數據型別,就叫Symbol基本型別
4、如果Symbol作爲key,用for in 回圈不出來
let syml = Symbol('aaa);
let syml = Symbol('strive);
let json = {
a: 'aa',
[symbol]:'bbb'
}
json[a] //aa
json[symbol] //bbb
for(let key in json){
console.log(key) //a 4、如果Symbol作爲key,用for in 回圈不出來
}
解決非同步問題,深度巢狀的問題
語法
function * show(){
yield
}
function * show(){
yield 'aaa'
yield 'bbb'
return 'ccc'
}
//呼叫
let sh = show()
console.log(sh) // 返回物件
console.log(sh.next())//{value: "aaa", done:false}
console.log(sh.next())//{value: "bbb", done:false}
console.log(sh.next())//{value: "bbb", done:true}
console.log(sh.next())//{value: undefined, done:true}
//以上呼叫,手動呼叫,麻煩
for...of自動遍歷generator,return的東西。它不會遍歷
for(let val of sh){
cosole.log(val)
}
// generator不僅可以配合for...of還可以結構賦值
function * show(){
yield 'aaa'
yield 'bbb'
yield 'ccc'
return 'ddd'
}
let [a,b,c,d] = show();
// aaa bbb ccc undefined
let [a,...b] = show();
//aaa ['bbb', 'ccc']
// 擴充套件運算子
...show() // aaa bbb ccc
Array.from(show()) ['aaa','bbb','ccc']
generator結合axios數據請求
function * gen(){
let val = yeild 'strive';
yield axios.get(''http://.../${val});
}
let g = gen();
let userName = g.next().value;
//g.next(userName).value -->promise
g.next(userName).value.then(res=>{
console.log(res.data);
});
非同步:不連續,上一個操作沒有執行完,下一個操作照樣開始。
同步:連續執行,上一個操作沒有執行完,下一個沒法開始。
關於非同步,解決方案:
1.回撥函數
2.事件監聽
3.發佈/訂閱
4.Promise物件
ES2017,規定async
const fs = require('fs');
//簡單封裝 fs封裝成promise版本
const readFile = function (filename){
return new Promise(resolve,reject)=>{
fs.readFile(filename,(err,data)=>{
if(err) reject(err);
resolve(data);
})
}
}
//promise
readFile('data/a.text').then(res=>{
console.log(res.toString());//aaa
return readFile('data/b.txt');
}).then(res=>{
console.log(res.toString())// aaa bbb
})
genertaor
function *gen(){
yield readFile('data/a.txt');
yield readFile('data/b.txt');
yield readFile('data/c.txt');
}
let g = gen();
g.next().value.then(res=>{
console.log(res.toString());
return g.next().value;
}).then(res=>{
console.log(res.toString());
return g.next().value;
}).then(res=>{
console.log(res.toString()) // aaa bbb ccc
})
async
async function fn(){
let f1 = await readFile('data/a.txt');
console.log(f1.toString());
let f2 = await readFile('data/b.txt');
console.log(f2.toString());
let f3 = await readFile('data/c.txt');
console.log(f3.toString());
}
async特點:
1.await 只能放到async函數裡
2.相比generator語意化更強
3.await後面可以是promise物件,也可以數位、字串、布爾
4.async函數返回是一個promise物件
5.只要await語句後面promise狀態變成reject,那麼整個async函數中斷執行
如何解決async函數中拋出錯誤,影響後續程式碼
a)try{
}catch(e){
}
b)promise本身catch
個人建議:只要await 都try catch
async function fn(){ //表示非同步,這個函數裏面有非同步任務
await //表示後面結果需要等待
}
//async
async function fn(){
return 'aaa';
}
fn() //Promise
fn().then(res=>{
console.log(res) // aaa
})
async function fn(){ //表示非同步,這個函數裏面有非同步任務
await //表示後面結果需要等待
}
//async
async function fn(){
throw new Error('出錯了')
}
fn() //Promise
fn().then(res=>{
console.log(res)
}),err=>{
console.log(err);//出錯了
}
// 或者
fn().then(res=>{
console.log(res)
}).catch(err=>{
console.log(err); //出錯了
})
async function fn(){
awiat Promise.reject('出錯了')
//可以try catch
try{
awiat Promise.reject('出錯了')
}catch(e){
}
//也可以promise catch
awiat Promise.reject('出錯了').catch(err=>{
console.log(err)
})
let a = await Promise.resolve('aaa');
}
fn().then(res=>{
console.log(res) // aaa
}).catch(err=>{
console.log(err)
})
數據結構:陣列,json,二元樹…
set數據結構,類似陣列,但裏面不能有重複值
用法:new Set([‘a’,‘b’]); key和value一樣
如果 new Set({})//報錯 但通過add方式是可以的{}
let arr = new Set(['a','b','c']);
//{'a','b','c'}
let setArr = new Set();
setArr.add('a') //新增
setArr.add('b') //新增
setArr.delete('a')//刪除
setArr.has('a') // false //判斷裏面有沒有此值
setArr.size() //個數
setArr.clear()//清除所有
// 回圈
for...of
for(let item of setArr){//預設是values
// a b
}
for(let item of setArr.keys()){
// a b
}
for(let item of setArr.values()){
// a b
}
for(let item of setArr.entries()){
// ['a':'a'] ['a':'b']
}
for(let [k,v] of setArr.entries(){
k->a v->a
}
setArr.forEach(value,index)=>{
value->a index->a
});
// 去重
let arr = [1,2,3,2,1];
let s = new Set(arr);
Array.form(s);
// 或者
[...new Set(arr)];
set數據結構變成陣列
[...set]
想讓set使用陣列的map filter先變成陣列
let arr1 = [...new Set(arr)];//set->arr
let set = new Set(arr1)//arr->set
WeakSet()儲存json 初始裏面新增東西是不行的,最好用add新增
WeakSet({})這樣寫不行報錯
weakSet沒有size,沒有clear,有add,has ,delete
let json = {
a:1,
b:2
}
let wSet = new WeakSet();
wSet.add(json);//{a:1,b:2}
類似json,但是json的鍵(key)只能是字串
map的key可以是任意型別
new Map();
let map = new Map();
let json = {
a:1,
b:2
}
map.set('a','aaa');
map.set(json,'aaa');
map.set('b',json); //設定值
map.get(json) //獲取 'aaa'
map.delete(key)//刪除
map.has(key)//判斷有沒有
map.clear()//清除所有
//回圈:
for(let [key,val] of map){//預設是entries
}
for(let key of map.keys()){
}
for(let val of map.values()){
}
map.forEach((value,key)=>{
// aaa a
}
WeakMap(): key只能是物件
let wMap = new WeakMap();
let json = {
a:1,
b:2
}
wMap.set(json,'aaa');
wMap.set('aa','nn');//報錯
數位(數值)變化
// 二進制:(binnary) 0b開頭
let a = 0b010101;
a//21
// 八進制:(octal) 0o開頭
let a = 0o666;
a //
//十六進制:
// 數位變化
let a = 2;
isNaN(a)//false
Number.isNaN(a)//false
Number.isFinite(a)//true //判斷是不是數位
Number.isInteger()//判斷數位是不是整數
Number.parseInt()
Number.parseFloat()
安全整數:
安全整數:-(253-1)到253包含-(253-1)和253
Number.isSafeInteger()
let a = 2**53
Number.isSafeInteger(a) //安全整數
Number.MAX_SAFE_INTEGER //最大安全整數
Number.MIN_SAFRE_INTEGER //最小安全整數
Math:
Math.abs()
Math.sqrt()
…
新增
Math.trunc()//截斷
Math.trunc(4.56)//4 截斷擷取,只保留整數部分
Math.sign(-50) //判斷一個數到底是正數、複數、0
-50->-1
50->1
0->0
-0->-0
其他值->NaN
Math.cbrt(27) // 3 計算一個數立方根
命名匹配
let str = "2018-03-20";
let reg = /(\d{4})-(\d{2})-(\d{2})/;
let dateArr = str.match(reg);
let year = dateArr[1]; //2018
let month = dateArr[2];//03
let day = dateArr[3];//20
1.命名捕獲
// 語法:(?<名字>)
let str = '2018-03-20';
let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
let {year,month,day} = str.match(reg).groups;
// 2018 03 20
反向參照:
// \1 \2 $1 $2
// 反向參照命名捕獲:
// 語法:\k<名字>
let reg = /^(?<strive>welcome)-\k<strive>$/;
reg.test('a-a'); //false
reg.test('welcome-welcome')//true
let reg = /^(?<strive>welcome)-\k<strive>$-\1$/;
reg.test('welcome-welcome-welcome')//true
2.替換
// $<名字>
let str = '2018-03-20';
let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
str.replace(reg,'$<year>/$<month>/$<day>')
//str-> 2018/03/20
str.replace(reg,'$<day>/$<month>/$<year>')
//20/03/2018
str.replace(reg,(...args)=>{
let {year,month,day} = args[args.length-1];
return `${year}/${month}/${day}`
})
dotAll模式----s
之前 '.'在正則裡表示匹配任意東西,但是不包括\n
let reg = /^\w+.\w+$/s;
let str = 'welcome-51mmr';
let str2 ='welcome\n51mmr'; //true
console.log(reg.test(str));//true
標籤函數
function fn(){
}
fn();//普通函數呼叫
function fn(args){
console.log(args);//['welcome',row:Array[1]]
return args[0].toUpperCase();
}
fn`welcome` //WELCOME
代理:擴充套件(增強)物件一些功能:
作用:比如vue中攔截
預警、上報、擴充套件功能、統計、增強物件等
proxy是設計模式一種,代理模式
語法:
new Proxy(target,handle)
new Proxy(被代理的物件,對代理的物件做什麼操作)
handle
{
set(){},//設定的時候乾的事
get(){},//獲取乾的事
deleteProperty(){},//刪除 'xxx' in target
has(){},//問你有沒有這個物件
apply(){},// 呼叫函數處理
....
}
例子
let obj = {
name: 'strive'
}
let newObj = new Proxy(obj,{
get(target,property){
return target[property]
}
})
newObj.name // strive
存取一個,存取一個物件身上屬性,預設不存在給underfined,
希望如果不存在錯誤(警告)資訊
let newObj = new Proxy(obj,{
get(target,property){
if(property in target){
return target[property];
}else{
console.warn(`${property}不在屬性上`)
}
}
})
DOM.div()
const DOM = new Proxy({},{
get(target,property){
//property DOM.xxx裏面的xxx
return function(attr={},...chidlen){
const el = document.createElement(property);
for(let key of Object.keys(attr)){
el.setAttribute(key,attr[key]);
}
for(let child of children){
if(tyoeof child === 'string'){
child = document.createTextNode(child);
}
el.appendChild(child);
}
return el; //<div id="div1" class="aaa">我是divhhh</div>
}
}
});
let oDiv = DOM.div({id:'div1',class:'aaa'},'我是div','hhh');
set()設定攔截
let obj = new Proxy({},{
set(target,property,value){
if(property == 'age'){
if(!Number.isInteger(value)){
throw new TypeError('年齡必須爲整數');
}
if(value>200){
throw new RangeError('年齡超標了');
}
}
target[property] = value;
}
})
obj.a =123;
obj.age = 202;//
deleteProperty()刪除
has()
let json = {
a:1,
b:2
}
let newJson = new Proxy(json,{
deleteProperty(target,property){
delete target[property];
},
has(target,property){
return property in target;
}
});
'a' in newJson // true
delete newJson.a; // {b:2}
Reflect反射
Object.xxx語言內部方法
Object.defineProperty放到Reflect物件身上,通過Reflect物件身上直接拿到語言內部物件
apply()攔截方法
function fn(){
return '我是函數';
}
let newFn = new Proxy(fn,{
apply(){
return '函數嗎?'
}
});
newFn(); //函數嗎 fn被攔截裏面內容不執行
Reflect反射
Reflect.apply(呼叫的函數,this指向,參數陣列)
fn.call()
fn.apply()類似
function sum(a,b){
return a+b;
}
let newSum = new Proxy(sum,{
apply(target,context,args){ //sum函數,this指向,參數陣列
return Reflect.apply(...arguments);
}
})
newSum(2,3); //5
Math.cell(4.5)//5
Reflect.apply(Math.cell,null,[9.8])//10
function show(...args){
console.log(this);
console.log(args);
}
show(1,2,3)// Window [1,2,3]
show.call('abc',[1,2,3])// -->abc [1,2,3]
show.apply('abc',[1,2,3])//--> abc [1,2,3]
Reflect.apply(show,'aaa',[1,2,3])// -->aaa [1,2,3]
//Object.xxx語言內部方法
//Object.defineProperty放到Reflect物件身上,
//通過Reflect物件身上直接拿到語言內部物件
'assign' in Object
Reflect.has(Object,'assign')//true
let json = {
a:1,
b:2
}
delete json.a // {b:2}
Reflect.deleteProperty(json,'a')//{b:2}