js的异步和同步,js是单线程语言:
同步:加入主线程,按顺序执行,即上一个同步任务结束后,本任务跟着执行。
异步:加入任务队列,等待主线程上任务都执行完毕,请求主线程后才能执行。
{
let you = "forever";
}
console.log(you);//报错,找不到you,因为you变量在块中。
//let命名一致冲突报错,但是var不会
let he = "老大";
let he = "我会等";//会报错。
//不存在变量自动提升,根据实际出现位置命名变量
console.log(her);//报错无法找到变量,但是若是var则是undefinded,能够找到变量。
let her = "Drling";
var的话,会把所有变量放在代码前面声明,到对应行后再赋值,所以如果是var不会报错。
//获取元素
let items = document.getElementsByClassName("item");
//循环遍历
for(let i = 0; i < items.length;i++){
items[i].onclick = function(){
items[i].style.backgroundColor = 'pink';
}
}
console.log("完成!");
这样可以,如果把循环中let换为var,则会出错,因为var是全局作用域,会在函数向外寻找时加至items[3],所以找不到元素颜色无法变换。
//常量声明
const ONE = 'go';
//不能修改(否则报错)
const TWO = 'thyShy';
//const TWO = 'xiaohu';修改已定义常量,报错。因为常量指向变化
const THREE = ["kuisang","永恩"];
THREE.push("凯隐");//不会报错,指向没变
console.log(THREE);
解构赋值允许按照一定规则,从数组或者对象中提取数值,赋给变量。
//数组结构赋值(根据顺序)
const me = ['大头儿子','小头爸爸','一休'];
let[you,he,her] = me;
console.log(you + he + her);
//声明对象
const him = {
name : '赵子龙',
sex : '男',
kill : function(){
console.log('七进七出,骁勇善战');
}
}
//根据变量名提取,不能随便改名。
let{name,sex,kill} = him;
console.log(name + sex + kill);
kill();//调用
A、声明
//声明
let four = `这首歌是写给黄淮。`;
//可以使用换行
let five = `
- 天使
- 魔鬼
- 上帝
`;
//若换成‘或者“则报错,不允许换行。
//字符串拼接
let six = `黄淮`;
let seven = `写给${six}`;
console.log(seven);
不同于之前使用+号拼接,这里使用${}。
如果对象的属性名要赋已经声明的变量,且变量名和属性名一致,则省写冒号和赋值;
对象中声明函数也可以简化为:函数名(){};
let myName = '托尼斯达克';
let myGo = function(){
console.log("fly");
}
const myObject = {
myName,//之前,myName:myName
myGo,
myLove(){
console.log('she love me too!');
}//之前 myLove:function(){}
}
//验证
console.log(myObject.myName);
myObject.myGo();
myObject.myLove();
const functionTest = (a,b,c) => {
return a + b - c;
}
let num = functionTest(4,5,1);
console.log(num);
简化函数声明中的this始终指向函数声明时所在的作用域所在的this下的值,例如在函数A中声明的函数B中的this就始终指向函数A,在对象中或者直接声明的函数始终指向window对象。
//1、this始终指向自声明后,始终如一。
window.name="我是windows";
const myCloud = {
name:"我是myCloud对象的云",
testOne : function(){
console.log(this.name);
},//原来方式声明
testTwo:()=>{
console.log(this.name);
}//简化方式声明
}
myCloud.testOne();
myCloud.testTwo();
//用call改变this指向,后原始方式变化,简化方式不变。
myCloud.testOne.call(window);
myCloud.testTwo.call(window);
输出结果:
即使用call函数改变testTwo使其指向myCloud也没有用,一直是window。
myCloud.testTwo.call(myCloud);//我是windows
/不能构造实例化对象
let youTestFun = (a,b)=>{
this.a = a,
this.b = b
}
const meTestFun = new youTestFun("我","你");//报错
我认为,还是跟this指向固定不变有关,所以在构造过程中无法动态变化赋值。
不能使用函数默认参数arguments。(注:非简化声明的函数存在arguments用来承接未声明但在实际调用中多出来的参数。)
//不能使用arguments
let youTestFunOne = ()=>{
console.log(arguments);
}
youTestFunOne("me");//报错找不到arguments
不使用简化方式:
let youTestFunOne = function(){
console.log(arguments);
}
youTestFunOne("me");//结果为arguments["me"]
当声明的函数只有一个参数或者函数中语句只用一句时,可以对箭头函数进行再简化,可以省略括号或花括号且那一条语句不需要return,默认为将结果作为返回值。
简化前:
let meTestFunh= (n) => {
return n + 1;
}
let heMe = meTestFunh(9);
console.log(heMe);
简化后:
let meTestFunh= n => n + 1;
let heMe = meTestFunh(9);
console.log(heMe);
实践一:
//需求,点击块后,2s后变色。
let chCon = document.getElementsByClassName("changeColorContain");
let chCoCon = chCon[0];
chCOCon.addEventListener("click",function(){
setTimeout(function(){
this.style.backgroundColor= "blue";
//这里this指向调用者windows,而window无style,会报错。
}, 2000);
});
修改一:this传导到元素
//需求,点击块后,2s后变色。
let chCon = document.getElementsByClassName("changeColorContain");
let chCoCon = chCon[0];
chCoCon.addEventListener("click",function(){
let _this = this;
setTimeout(function(){
_this.style.backgroundColor= "blue";
//——this往上找找到this,而上面this指向元素chCoCon。
}, 2000);
});
修改二: 通过箭头函数,指向所在所用域下this的值,即(元素chCoCon)
//需求,点击块后,2s后变色。
let chCon = document.getElementsByClassName("changeColorContain");
let chCoCon = chCon[0];
chCoCon.addEventListener("click",function(){
setTimeout(()=>{
this.style.backgroundColor= "blue";
}, 2000);
});
实践二:
//从数组中筛选出2的偶数
const numSub = [2,3,53,88,100,23];
const result = numSub.filter(function(item){
if(item % 2 == 0){
return true;
}else{
return false;
}
})
console.log(result);
改进:
//从数组中筛选出2的偶数
const numSub = [2,3,53,88,100,23];
const result = numSub.filter(item=> item % 2 == 0)
console.log(result);
const skyFun = (a,b,c,d=10)=> a + b + c + d;
//不给值,有默认值就是默认值,否则undifinded
let numSkey = skyFun(3,54,3);//70
let numSky = skyFun(1,2,3,9);//15
console.log(numSkey + " " + numSky);
如果函数中传入参数是对象,则要先将对象写成参数解构形式,然后赋默认值。
//和解构赋值结合使用
let outBody = ({name,sex,age=18})=>{
console.log("刚满" + age + "岁~");
}
const myLove = {
name: '老爹',
sex: '男',
age: 20
}
outBody(myLove);//传入对象,age有值为20;
outBody({name:"爱人",sex:"女"});//传入对象,无age,使用默认值18。
//ES5可变参数接收
let myChangeFun = function(){ console.log(arguments);};
myChangeFun("萧炎","荒天帝","美杜莎","七彩吞天蟒");//arguments以对象形式保存
//ES6可变参数接收
let myChangeFunTwo = (...args)=> {console.log(args);};
myChangeFunTwo("萧炎","荒天帝","美杜莎","七彩吞天蟒");//该风格,以数组形式保存。
结果展示:
可以将数组中的元素变为以逗号隔开的参数序列:
//扩展运算符
let myArray = ["萧炎","荒天帝","美杜莎","七彩吞天蟒"];
let showMy = function(){console.log(arguments)};//是一个参数,类型是数组。
//正常传参数,数组,1个参数
showMy(myArray);
//用扩展运算符,变量,4个参数
showMy(...myArray);
//利用扩展运算符合并
let myArrayThree = [...myArrayOne,...myArrayTwo];
console.log(myArrayThree);
变为数组后可以使用数组的一些方法
//伪数组
let divs = document.querySelectorAll("div");
//真数组
let myDivs = [...divs];
console.log(divs);
console.log(myDivs);
let one = ["邓紫棋"];
let two = ["hh"];
two = [...one];
console.log(two);
这种克隆是浅拷贝,基本类型复制值,引用类型复制引用地址,指向同一个值,新对象(引用类型)会影响原对象。即是说,当复制的数组中还有数组,就是复制最里层数组地址。
Symbo是ES6中新出现的基本数据类型,是继前五大数据类型(字符串,null,undefinded,Object,num(数字),布尔)后出现的第六大数据类型。
因为对象中的键值在ES5中只能使用字符串,会存在key值冲突的风险,尤其是当合作过程中拿到一个陌生的对象,很容易在添加方法过程中导致key重复。故而Symbol诞生,它的特点就是唯一,即使在利用Symbol中函数生成同样字符串,也是不同键值,相等运算为false。
//symbol()的使用
let rabbit = {
name: '小白兔',
age: 18,
skip(){
console.log("唱跳rap");
},
eat(){
console.log("吃的很多!");
}
}
//作用一:防重复key命名
//方式一:
let model = {
skip: Symbol(),
eat: Symbol()
}
rabbit[model.skip] = function(){
console.log("新增skip方法");
}
rabbit[model.eat] = function(){
console.log("新增的吃方法");
}
console.log(rabbit);
//方式二
let tigger = {
name:"微少",
age: 20,
[Symbol("fly")](){
console.log("轰轰轰!");
},
[Symbol("fly")](){
console.log("哈哈哈");
}
}
console.log(tigger);
作为一种基础数据类型,在作为唯一键值称为对象中的属性,也可以在声明对象属性时调用内置属性生成对象的key值,这些key下的属性或者方法会在特定时机被调用。
当属性对应的类被作为instanceof的对象时,其对应方法会被自动调用
//Symbol内置属性
class people{
static[Symbol.hasInstance](){
console.log("我是Symbol.hasInstance作为键值的方法,我被自动调用了");
}
}
let Bob = {};
//当people被用于 instanceof 时,该方法会被自动调用
Bob instanceof people;
运行结果:
还有很多内置属性,可以搜索查看,基本都是在特定情况下,自动调用某种函数。
ES6引入迭代器接口,只要实现了迭代器接口的数据类型,就可以使用for.....of....循环语法。
Array、Arguments、Set、Map、String、TypedArray、NodeList
Array使用迭代器演示:
//iterator迭代器,默认实现迭代器的结构
let red = ["红","蓝","白","紫","天下"];
for(let zi of red){
console.log(zi);//of 展示内容
}
for(let wo in red){
console.log(wo);//in 展示下标
}
let red = ["红","蓝","白","紫","天下"];
let myIterator = red[Symbol.iterator]();
for(let i = 0; i <= red.length;i++){
console.log(myIterator.next());
}
let contain = {
name: 'shao杰',
lover:["米老鼠","柯洁","tiancai","小八嘎" ],
[Symbol.iterator](){
let index = -1;
let _this = this;
return{
next(){
if(index == -1){
index++;
return {value: _this.name,done: false}
}else if(index<_this.lover.length - 1 && index != -1){
index++;
return {value:_this.lover[index],done:false}
}else{
return {value:_this.lover[index],done:true};
}
}
}
}
}
for(let one of contain){
console.log(one);
}
生成器函数返回的是一个迭代器对象,通过调用next方法执行其中语句,yield语句相当于暂停标志,每次next,执行一段代码,后返回yield语句后内容
//生成器函数
function * lover(){
console.log("one,我是天选也是唯一");
yield "one",
console.log("冲天香阵透长安");
yield "two",
console.log("i am iron man");
yield "three"
}
//调用生成器函数
room = lover();
room.next();//每次调用都会执行一个yield之前的句子,并返回yield后数据。
room.next();
//生成器函数
function * lover(param,me){
console.log(param + "我爱你!" + me);
yield "one",
console.log("冲天香阵透长安");
yield "two",
console.log("i am iron man");
yield "three"
}
//调用生成器函数
room = lover("美女","我");
room.next();//每次调用都会执行一个yield之前的句子,并返回yield后数据。
next中传入的参数会作为上一个yield语句的返回值。
//生成器函数
function * lover(){
console.log("我爱你!");
let oneReturn = yield "one";
// 这里返回的是上一个yield的返回值
console.log("上一个yield的返回值是" + oneReturn);
yield "two";
console.log("i am iron man");
yield "three"
}
//调用生成器函数
room = lover();
let reture = room.next();//每次调用都会执行一个yield之前的句子,并返回yield后数据。
console.log(reture);
room.next("你好老弟");
room.next();
原方式:(每步应该添加定时器,这里省略了)
function getOrder(){
let data = "订单数据";
console.log("获得了订单!");
return data;
}
function getCust(){
let dataUp = getOrder();
let data = "顾客信息";
console.log("获得了订单数据:" + dataUp + "顾客信息。");
return data + dataUp;
}
function getAll(){
let dataUp = getCust();
let data = "全部信息";
console.log("获取了全部" + data + dataUp);
return dataUp + data;
}
getAll();
使用生成函数:(这里每一步必须使用定时器,否则报错!)
function getOrder(){
setTimeout(()=>{
let data = "订单数据";
zongzi.next(data);//调用下一步,并为OrderData赋值;
},2000)
}
function getCust(){
setTimeout(()=>{
let data = "顾客信息";
zongzi.next(data);
},2000)
}
function getAll(){
setTimeout(()=>{
let data = "全部信息";
zongzi.next(data);
},2000)
}
function * myTest(){
let OrderData = yield getOrder();
console.log("拿到了订单数据" + OrderData);
let CustData = yield getCust();
let CuOrData = CustData + OrderData;
console.log("拿到了订单和客户数据" + CuOrData);
let allData = yield getAll();
let zongInfo = allData + CuOrData;
console.log("拿到所有数据" + zongInfo);
}
let zongzi = myTest();
zongzi.next();
//两个参数,名称随意,都是函数,第一个成功时调用,改变testOne状态为成功。
//第二个失败时调用,改变testOne状态为失败。
let testOne = new Promise(function(get,reject){
setTimeout(()=>{
//一、错误情况
// console.log("一堆逻辑");
// console.log("有错误出现");
// error = "计算有误";
// reject(error);//传入错误的原因,参数。
//二、成功情况
value = "太酷了";
get(value);
})
})
// then两个参数,第一个函数状态为成功执行,第二个状态为失败执行。
testOne.then((value)=>{
console.log("执行成功,获取到的数据为" + value);
},(error)=>{
console.log("错误的原因是" + error);
console.log("一堆对出现错误后的处理逻辑");
})
//读取文件到控制台
const fs = require('fs');
fs.readFile("./test.txt",(error,data)=>{
if(error)throw error;//出错的逻辑
console.log(data.toString());
})
//读取文件到控制台
const fs = require('fs');
// fs.readFile("./test.txt",(error,data)=>{
// if(error)throw error;//出错的逻辑
// console.log(data.toString());
// })
let myPromise = new Promise(function(get,back){
fs.readFile("./test.txtm",(error,data)=>{
if(error){
back(error);//传入原因
}else{
get(data);
}
})
});
myPromise.then((data)=>{
console.log(data.toString());
},(error)=>{
console.log(error);
});
//Set集合,不可重复
let mySet = new Set([1,1,2,2,3,4,3,2]);
//添加元素
mySet.add(0);
//删除元素
mySet.delete(1);
//返回元素个数
let all = mySet.size;
console.log(mySet + "总数是" + all);
//判断是否存在某元素
console.log(mySet.has(0));
//转化数组,因继承Interator接口,所以可以使用扩展运算符和for...of
let arrayMe = [...mySet];
console.log(arrayMe);
//遍历
for(let i of mySet){
console.log(i);
}
//清空Set
mySet.clear();
console.log(mySet);
结果:
//集合操作
let oneArr = [1,1,2,2,3,3,0,0,4];
let twoArr = [4,4,5,5,3,6,6];
//交集
let oneSet = new Set([...oneArr]);//去重
let twoSet = new Set([...twoArr]);
let resultSet = [...oneSet].filter((item)=> twoSet.has(item));
console.log(resultSet);
//并集
let resultSetTwo = new Set([...oneArr,...twoArr]);
console.log(resultSetTwo);
//差集
let resultSetThree = [...oneSet].filter((item) => !twoSet.has(item));
console.log(resultSetThree);
结果:
Map很像对象,里面是键值对的数据结构,和对象不同,任何类型(包括对象)都可以成为Map的键值,继承了Interator接口,可以使用扩展运算符和for...of..语句。
//Map
let myMap = new Map();
myMap.set("姓名","道发");
myMap.set([1,2,3],"哈哈");
let object = {
name: "唧唧",
age: 18
}
myMap.set(object,"我爱你!");
for(let o of myMap){
console.log(o);
}
Class是对象的一种规范和模版,简化了之前声明构造函数的过程,采用更易理解的方式声明对象的模版。
//声明构造函数
function people(name,lover){
this.name = name;
this.lover= lover;
}
//添加方法
people.prototype.sayLove = function(){
console.log(this.lover + "我爱你!");
}
//创建对象,调用方法
let onePeople = new people("杜若衡","天流芳");
onePeople.sayLove();
//现创建Class
class PP{
//构造方法,new对象时会自动调用
constructor(name,lover){
this.name=name;
this.lover=lover;
}
//函数声明固定格式,不可为name:function()方式
sayLove(){
console.log(this.lover + "我爱你!");
}
}
//创建对象,调用方法
let PPOne = new PP("琉璃月","陌上桑");
PPOne.sayLove();
只属于类或者构造函数的属性或者函数。
//静态成员
//构造函数的静态成员
function wo(){
}
//下面的属性属于构造函数,不属于对象。
wo.name = "郦道元";
wo.age = 18;
wo.prototype.trueName="你";
let woOne = new wo();
//class的静态成员
class hi{
static name = "郦道元";
static age = 18;
trueName = "你";
constructor(){
}
}
let hiOne = new hi();
console.log(wo.age);
console.log(hi.age);
//对象和构造函数的原型中属性相通,和在其内部直接声明的属性。
console.log(woOne.trueName);
console.log(hiOne.trueName);
console.log(woOne.age);//undefined
console.log(hiOne.age);//undefined
get和set后面跟属性名,当要获取该属性就会调用get函数,当要修改就会调用set函数,注意不要返回自身,不然会陷入循环调用地狱。
class People{
myPrice;
constructor(first,end){
this.first = first;
this.end = end;
}
get price(){
this.myPrice = this.first + this.end;
return this.myPrice;
}
set price(value){
this.myPrice = value;
return myPrice;
}
}
let hei = new People(1000,800);
let wo = hei.price;
console.log(hei.price);会调用get
//继承
function Phone(band,type){
this.band = band;
this.type = type;
}
Phone.prototype.say = function(){
console.log("我是" + this.band + "牌子的" + this.type);
}
function SmartPhone(band,type,price,color){
Phone.call(this,band,type);
this.price = price;
this.color = color;
}
//将子构造函数原型指向父类的原型,继承父类的方法
SmartPhone.prototype = Phone.prototype;
//创造对象检查
let SmartTrue = new SmartPhone("锤子","智能手机",1000,"红色");
SmartTrue.say();
console.log(SmartTrue);
class Phone{
constructor(band,type){
this.band = band;
this.type = type;
}
say(){
console.log("我是" + this.band + "的" + this.type);
}
}
class SmartPhone extends Phone{
constructor(band,type,price,color){
super(band,type);
this.price = price;
this.color = color;
}
//新增方法
speak(){
console.log("我是" + this.band + "手机,我为自己代言!");
}
}
//声明对象并尝试
let myPhone = new SmartPhone("苹果","智能手机",4900,"红色");
myPhone.say();
myPhone.speak();
截取上面例子的子类展示重写
class SmartPhone extends Phone{
constructor(band,type,price,color){
super(band,type);
this.price = price;
this.color = color;
}
//新增方法
speak(){
console.log("我是" + this.band + "手机,我为自己代言!");
}
//重写方法
say(){
console.log("我是重写后的方法");
}
}
//声明对象并尝试
let myPhone = new SmartPhone("苹果","智能手机",4900,"红色");
myPhone.say();
myPhone.speak();
//1、Number
Number.EPSILON;//该属性是Number计算的最小误差,通过该属性改变比较结果。
function equal(a,b){
if(a - b < Number.EPSILON){
return true;
}else{
return false;
}
}
let a = 0.2;
let b = 0.5;
console.log(equal((a+b),0.7));
//2、判断有限数,是为true,不是为false
console.log(Number.isFinite(100/0));//false
console.log(Number.isFinite(34));//true
console.log(Number.isFinite(Number.PI))//false
//3、判断数的正负,正为1,负为-1,0为0
console.log(Math.sign(3));
console.log(Math.sign(-3));
console.log(Math.sign(0));
//4.判断是否NaN
console.log(Number.isNaN(100/0));
console.log(Number.isNaN("天"));
//5.将字符串转化为数值
console.log(Number.parseInt("1243544"));
console.log(Number.parseFloat("1.23344"));
//6.判断一个数是否为整数
console.log(Number.isInteger(45));
console.log(Number.isInteger(2.133));
//7.将浮点数的小数部分抹去
console.log(Math.trunc(2.99));//默认下舍入
判断A和B两个数是否完全相等,和===功能相似,但是对NaN之间比较的判断结果不一,is为true,===为false。
let one = Object.is(2,2);//相当于===,判断两个数是否完全相等。
//例外,NaN对于===是faluse,对于is来讲是true;
console.log(one);
console.log(Object.is(NaN,NaN));
令对象B中内容,根据同key覆盖进行覆盖,覆盖对象A中的属性。对于属性A中没有属性B中存在的属性,在A中增加,对于A中存在,但B中不存在的属性,保持不变。
let ObOne = {
name: "小天才",
age: 18,
fly(){
console.log("小天才飞上天了!");
},
mySelf: "我独苗"
}
let ObTwo = {
name: "大猪蹄子",
age: 20,
fly(){
console.log("大猪蹄子飞上天了");
},
he:"别浪"
}
//让后者覆盖前者
Object.assign(ObOne,ObTwo);
console.log(ObOne);
let me = {
name: "我",
age: 19
}
let you = {
name: "你",
age: 20,
say(){
console.log("你看着我眼睛~");
}
}
//将后者作为前者的原型对象(插入原型链)
Object.setPrototypeOf(me,you);
ES5时我们引入js文件,每个js文件中的变量不能出现命名冲突,这样就导致很多麻烦,所以引入模块化,也适用于大型项目的合作开发。
模块化的好处有:防止命名冲突、方便代码复用、维护升级方便。
模块之间要相互调用,就要用到暴露和引用语法,我们用一个js文件来代表一个模块。
因为要用不同文件,所以要解决跨域问题,这个问题可以用Live Server插件来解决,下载之后,在vs code右下角打开,然后在文件中右击,选择用live Server运行,那么该插件会自动扮演一个代理服务器,这样就能够解决跨域问题了。
export const name = "jack";
export const rose ={
name: "rose",
age: 20,
say(){
console.log("i love you jack!");
}
}
//export是分别暴露。
结果:
const name = "jack";
const rose ={
name: "rose",
age: 20,
say(){
console.log("i love you jack!");
}
}
//统一暴露
export{
name,rose
}
export default{
name : "jack",
rose:{
name: "rose",
age: 20,
say(){
console.log("i love you jack!");
}
}
}
引用方式也要发生变化,因为默认方式相当于在中间又加了个对象。
//a 直接为default的别名
import a from "./testAgain.js";
//解构赋值,设置别名
import {default as a} from "./testAgain.js";
//引入后直接,变为属性值使用,可用as设置别名
import {name,rose} from "./testmoren.js";
当模块过多时,我们可以使用主模块使解构更加清晰,如上有testAgain.js和testmoren.js,这时再增加主模块(app.js),在主模块中使用引用语句。
import {name,rose} from "./testmoren.js";
import {default as me} from "./testAgain.js";
console.log(me);
console.log(name);
console.log(rose);
import $ from 'jquery';
//原方式:let jquery = require('jquery');
includes检测数组是否含有某元素返回的是布尔值。indexof返回的是1或者-1。
let array = ["红楼梦","大闹天宫","西厢记"];
console.log(array.includes("金瓶梅"));
console.log(array.indexOf("高老头"));
console.log(Math.pow(2,20));
console.log(2 ** 20);
async函数是返回值是Promise对象,Promise对象中的状态根据函数返回情况不同而不同。
函数返回值填充Promise对象的result部分。
async function me(one,two){
return "我会等";
}
let hi = me();
console.log(hi);
Promise的失败调用函数传参或成功调用函数传参,作为返回Promise的result。
Promise的执行结果作为返回Promise的status
async function me(one,two){
let PromiseMe = new Promise((fulfilled,reject)=>{
if(one == 1 && two == 2){
fulfilled("执行成功");
}else {
reject("执行失败!");
}}
);
return PromiseMe;
}
console.log(me(1,2));
console.log(me(1,1));
await指令只能出现在async函数体中,await指令后跟返回值为Promise对象的函数,如果Promise对象status为成功,则await返回result,Promise对象status为失败,则直接抛出错误。
function mid(one,two){
let PromiseMe = new Promise((fulfilled,reject)=>{
if(one == 1 && two == 2){
fulfilled("执行成功");
}else {
reject("执行失败!");
}}
);
return PromiseMe;
}
async function me(one,two){
try{
let winRe = await mid(one,two);//成功后返回结果
console.log(winRe)
}catch(error){
console.log(error);
}
}
me(1,2);
me(1,1);
const fs = require('fs');
function getFile(path){
return new Promise((fulfilled,reject)=>{
fs.readFile(path,(err,data)=>{
if(err) reject("出错了!");
fulfilled(data.toString());
})
})
}
async function mid(path){
try{
let result = await getFile(path);
console.log(result);
}catch(err){
console.log(err);
}
}
mid("./test.txt");
function sendAJAX(){
return new Promise((fulfilled,reject)=>{
let ajax = new XMLHttpRequest();
ajax.open("get","https://api.xygeng.cn/one");
ajax.send();
ajax.onreadystatechange = function(){
if(ajax.readyState == 4){
if(ajax.status >= 200 && ajax.status <=399){
fulfilled(ajax.response);
}else{
reject(ajax.status);
}
}
}
})
}
async function sendA(){
let content = await sendAJAX();
console.log(content);
}
sendA();
const obj = {
name: "令斛楚",
age: 20,
lover:["清漪","美杜莎","傻妞"],
do(){
console.log("fly");
}
}
//返回对象键值构成的数组
const objKeyArr = Object.keys(obj);
//返回对象属性值构成的数组
const objValueArr = Object.values(obj);
//返回对象属性和键构成的键值对
const objKVArr = Object.entries(obj);
//变为Map集合
const objToMap = new Map(objKVArr);
console.log(objKeyArr);
console.log(objValueArr);
console.log(objKVArr);
描述对象中规定了更清晰的属性描述,包括value,可写(writed)、可配置(configurable)、可枚举(enumerable)。
通过Object.create()方法创建的对象,必须制定描述细节属性。
const obj = {
name: "令斛楚",
age: 20,
lover:["清漪","美杜莎","傻妞"],
do(){
console.log("fly");
}
}
let objDes = Object.getOwnPropertyDescriptors(obj);
console.log(objDes);
//第一个参数是要继承的对象,第二个是新创建的对象结构
let obj2 = Object.create(null,{
name:{
value: "卞之琳",
writable: true,
configurable: true,
Enumerable: true
}
})
console.log(obj2);
function getObjProperty({name,age,...other}){
//当传入对象的一些属性没被显示标出,就会被存入other
console.log(name);
console.log(age);
console.log(other);
}
const obj = {
name: "令斛楚",
age: 20,
lover:["清漪","美杜莎","傻妞"],
do(){
console.log("fly");
}
}
getObjProperty(obj);
function getObjProperty({name,age,...other}){
//当传入对象的一些属性没被显示标出,就会被存入other
console.log(name);
console.log(age);
console.log(other);
}
const obj = {
name: "令斛楚",
age: 20,
lover:["清漪","美杜莎","傻妞"],
do(){
console.log("fly");
}
}
const obj2 = {
name2: "风清扬",
age: 23
}
//将对象拆解到新的对象。
let objArr = {...obj};
console.log(objArr);
//合并对象到新的对象,如果有属性名冲突,则后面覆盖前面
let objArr2 = {...obj,...obj2};
console.log(objArr2);
let zongUrl = '尚';
let ZZ = /(.*)<\/a>/;
//接收正则表达式接收到的数据,小括号是子正则
let result = ZZ.exec(zongUrl);
console.log(result[0]);
console.log(result[1]);
console.log(result[2]);
console.log(result);
let zongUrl = '尚';
let ZZ2 = /(?.*)<\/a>/;
let result2 = ZZ2.exec(zongUrl);
console.log(result2.groups.url);
console.log(result2.groups.content);
判断筛选内容后面是否满足条件:
let love = "1314521冲锋888杀呀";
//如果数字会随机变化,并且筛选后面为杀的数字。
let outSha = /\d+(?=杀)/;
let end = outSha.exec(love);
console.log(end);
判断筛选内容前面是否满足条件:
let love = "1314521冲锋888杀呀";
let forContent = /(?<=锋)\d+/;
let end2 = forContent.exec(love);
console.log(end2);
与上结果一致。
let text = `
天下无双
2022/12/01
冲天
2003/11/23
`;
//原来方式:用\s+匹配换行和空格
let ZZ = /\s+(.*?)<\/a>\s+(.*?)<\/p>/;
console.log(ZZ.exec(text));
//现在使用dotAll模式,用.除换行外的任何匹配任何字符
let ZZ2 = /
.*?(.*?)<\/a>.*?(.*?)<\/p>/s;
console.log(ZZ2.exec(text));
//Object.fromEntries 用键值类型数组元素或者map构造对象
let you = Object.fromEntries([["name","陈旺财"],["age",19],["lover","托尼"],["you","你"]]);
console.log(you);
//与上一个过程相逆
let me = Object.entries(you);
console.log(me);
//trimstart清除字符串开头空格 trimend 清除字符串后面空格
let me = " i love you ";
console.log(me.trimEnd());
console.log(me.trimStart());
//数组方法扩展
let arr = ["我是谁","我是天王老子","哈哈",['天下有约',"哈哈"]]
//将二维数组展开为一维数组
let chong = arr.flat();
console.log(chong);
//flatMap当要遍历的数组中有元素有多维数组,用此函数遍历可以将元素自动降维。每次遍历都会
//执行一个回调函数
//map函数也是每次执行一个回调函数,但是不会自动降维。
let resultMe=arr.flatMap(item => [item]);
let resultYou = arr.map(item => [item]);
console.log(resultMe);
console.log(resultYou);
let mySymbol = Symbol("哇哈哈");
let bin = mySymbol.description;
console.log(bin);
//为类添加私有属性
class myName{
//公有属性
name = "天下";
//私有属性,仅函数内部能够调用
#age = 19;
constructor(name,age){
this.#age = age;
this.name= name;
}
say(){
console.log(this.name + "" + this.#age);
}
}
let trueName = new myName("冲天",19);
trueName.say();
console.log(trueName.age);//undefined,私有属性无法外部使用
批量执行Promise:
//批量执行Promise
let myPromiseOne = new Promise((win,reject)=>{
setTimeout(()=> {win("成功获取数据1!");},1000);
})
let youPromiseTwo = new Promise((win,reject)=>{
setTimeout(()=>{reject("获取数据失败!");},1000);
})
let resultPromise = Promise.allSettled([myPromiseOne,youPromiseTwo]);
console.log(resultPromise);
//Promise.all()一荣俱荣,一损俱损;
let resultPromiseTwo = Promise.all([myPromiseOne,youPromiseTwo]);//报错
//String的matchAll方法,与正常的exec加上sg不同,该方法返回的是迭代器对象。
let text2 = `
天下无双
2022/12/01
冲天
2003/11/23
`;
let zzM = /.*?(.*?)<\/a>.*?(.*?)<\/p>/sg;
let allResult = text2.matchAll(zzM);
for(let m of allResult){
console.log(m);
}
//下面执行next不能和上面循环共同出现,不然next在下面执行时指向空。
console.log(allResult.next());
console.log(allResult.next());
用来对传入对象类型的参数进行属性是否存在判断:
//可选链操作符,用于对深层次对象类型参数进行属性判断
function main(forEach){
//原来判断,如果无错,会返回,如果有错直接报
//let all = forEach && forEach.name && forEach.name.detailName && forEach.name.detailName.hiName;
//使用可选链操作符,有错返回undefined
let all = forEach?.name?.detailName?.hiName;
console.log(all);
}
main({
name:{
detailName:{
hiName: "大志"
}
},
age: 18
});
//大整数类型
//1、声明
let intMe = 193443n;
console.log(intMe,typeof(intMe));
//2、函数将变量转化为大整型
let intHe = 18389384;
let intRes = BigInt(intHe);
console.log(intRes,typeof(intHe),typeof(intRes));
//3、大整型计算
//获取最大int数,正常情况下,这个数再加2就不会再往上加了;
let bigInt = Number.MAX_SAFE_INTEGER;
let nomalIntAll = bigInt + 2;
let BigIntAll = BigInt(bigInt) + BigInt(2);//注意大整型不能和整型计算
console.log(bigInt);
console.log(nomalIntAll);
console.log(BigIntAll);
globalThis始终执行windows对象,无论在任何位置,都可以使用它对windows对象进行操作。
外部js模块:
export function me(){
alert("你好!");
}
动态引入:
//原方式,这种方式是在文件加载的时候直接引入
// import * as hello from "./app.js";
//import函数会在事件发生时再引入模块
let button = document.getElementById("myButton");
button.addEventListener("click",()=>{
import("./app.js").then(module =>{
module.me();});});