文章目录
变量声明
let(相当于之前的var)
let注意事项:
- 1.没有预编译,不存在变量提升
- 2.在代码块内,在let定义变量之前就是用变量会报错。先定完才能使用
示例:
alert(a);
let a = 15;
//报错
- 3.同一个作用域里面,不能重复定义变量
let a = 15;
let a = 14;
//这样写会报错
- 4.for循环,for循环里面是父级作用域,{}里面又是一个作用域
let arr = [];
for (let i = 0; i < 5; i++) {
arr[i] = function() {
console.log(i);
}
}
arr[3]();
//3
//如果将let换成var,结果为5
const(常量,定义好了不能改变)
const注意事项:
- const定义的变量不能修改
- const定义完变量必须有值,不能后赋值,也不能修改
const a;
a = 2;
console.log(a);
//会出现语法错误
- 如果用const定义一个对象(数组),对象里面的值是可以修改的,因为js中无论是数组还是对象,传值方式都是引用传递
块级作用域
{
//块级作用域
}
(function(){
//TODO
})()
//块级作用域的功能就相似于于立即执行函数的功能
{{{{{let b = 2;{{{{{{let b = 1;}}}}}}}}}}}
//这两个b相互之间不会影响
像if(){},for(){},while(){}这些都有两个作用域()里面和{}里面
解构赋值
几个用法示例:
//解构赋值时要一一对应
//1.
let [a,b,c] = [1,2,3];
console.log(a,b,c);//1,2,3
//2.
let [a,[b,c]] =[12,[5, 6]];
//3.
let json ={
name:'qwe',
age:18,
job:'student'
};
let {name,age, job} = {
name:'qwe',
age:18,
job:'student'
};
console.log(name,age,job);
//4.
let json ={
name:'abc',
age:18,
job:'码农'
};
let {name:n,age:g, job:a} = json;//可以给name,age,job重新取一个名字,如果打印name,age,job会显示is not defined
console.log(n,g,a);
//5.
//可以给c设置一个默认值,不设置则打印undefined
let [a, b,c='暂无数据'] = ['aa','bb'];
console.log(a,b,c);
//6.在函数传参中的应用
function show({a,b='默认'}){
console.log(a, b);
}
show({
a:1
})
//7.解构赋值可以很方便的交换两个数的值
let a = 12;
let b = 5;
[a,b] = [b,a];
console.log(a,b);//5,12
字符串模板
``(字符串模板)
- 优点:
1.可以随便的换行
2.${变量名}
- 示例:
let name ='Strive';
let age = 18;
let str = `这个人叫${name}, 年龄是 ${age}岁`;
console.log(str);//这个人叫Strive, 年龄是 18岁
- 字符串查找
str.indexOf() 返回索引(位置) ,没找到返回-1
str.includes() 返回索引(位置) ,没找到返回-1
let str = 'apple banana2 pear';
alert(str.includes('banana'));//true
- 字符串是否以谁开头:
str.startsWith(检测东西)
let str2 ='https://www.baidu.com/';
console.log(str2.startsWith('http'));
- 字符串是否以谁结尾:
str.endsWith(检测东西)
let str2 = 'aaaa.html';
console.log(str2.endsWith('png'));
- 重复字符串:
str.repeat(次数);
let str = 'asd';
console.log(str.repeat(2));//asdasd
- 填充字符串:
str.padStart(整个字符串长度, 填充东西) 往前填充
str.padEnd(整个字符串长度, 填充东西) 往后填充
str.padStart(str.length+padStr.length, padStr)
let str = 'apple';
let padStr = 'x';
console.log(str.padStart(str.length+padStr.length, padStr));
- 小练习:
<ul id="ul1">
</ul>
let data = [
{ title: 'qweqweqweqweqweqe', read: 100 },
{ title: 'asdasdasdasdasfafafgzxczxvz', read: 9 },
{ title: 'werfervrthtynyunmjm', read: 10 },
{ title: 'wqwvrwbymu,obrbervc', read: 180 },
{ title: '21314234x45325bv4 b4v43c3c', read: 900 }
]
window.onload = function () {
let ul1 = document.querySelector('#ul1');
for (let i = 0; i < data.length; i++) {
let ol1 = document.createElement('li');
ol1.innerHTML = `<span>${data[i].title}</span>
<span>阅读人数:${data[i].read}</span>
<a href="javascript:;">详情</a>`;
ul1.appendChild(ol1);
}
};
函数变化
参数变化
- 1.函数默认参数
function show(a='456',b='123'){
console.log(a,b);
}
show();
//不传参数则打印默认值,如果默认值也没有则是undefined undefined
//也可以穿的是一个对象
function show({x=0,y=0}={}){
console.log(x,y);
}
show();
- 2.函数参数默认已经定义了,不能再使用let,const再定义
function show(a=18){
let a = 101; //错误
console.log(a);
}
show();
扩展运算符、Rest运算符(…)
-
用法简介:
[1,2,3,4] -> … [1,2,3,4] -> 1 2 3 4,5
1 2 3 4 5 -> …1 2 3 4 5 -> [1,2,3,4,5] -
用法示例
let arr = ['apple','banana','orange'];
console.log(arr);
console.log(...arr);//apple banana orange
- 在参数上的用法
function show(...a){
console.log(a);
}
show(1,2,3,4,5);//[1,2,3,4,5]
//也可以反过来使用
function show(a,b,c){
console.log(a,b,c);
}
show(...[1,9,8]);
箭头函数
//写法
() =>{
//语句
//return
}
- 示例:
//示例1
// function show(){
// return 1;
// }
// console.log(show());
let show = ()=>1;
console.log(show());
//示例2
/* function show(a,b){
return a+b;
}
console.log(show(12,5)); */
let show = (a,b)=>a+b;
console.log(show(12,5));
//示例3
let show=(a=12,b=5)=>{
console.log(a,b);
return a+b;
};
show();
- 箭头函数this的指向
var id = 10; //用var定义一个全局变量,属于window, let,const不同
let json={
show:function(){
setTimeout(()=>{
alert(this.id);
},2000);
}
};
json.show();//结果为undefined
箭头函数中的this指向的是定义函数(show)所在的对象(json中),json中没有id所以为undefined
- 注意事项
1.箭头函数里面没有arguments, 用 ‘…’
2.箭头函数不能当构造函数
/* function show(){
this.name='abc';
} */
let show = ()=>{
this.name='abc';
}
let s=new show();
alert(s.name);
//Uncaught TypeError: show is not a constructor
数组
新增一个运算符(**)
用法:
//Math.pow(2,3) 相当于 2 ** 3
for…of…
-
arr.keys() 数组下标
-
arr.entries() 数组的某一项
-
用法示例:
let arr = ['apple','banana','orange','tomato'];
for(let val of arr){
console.log(val);
}
for(let index of arr.keys()){
console.log(index);
}
for(let item of arr.entries()){
console.log(item);
}
for(let [key, val] of arr.entries()){
console.log(key,val);
}
Array.form()
- 作用:可以将类数组对象装换成数组,(proto : Array)
function show(){
let args= Array.from(arguments);
args.push(6);
console.log(args);//[1,2,3,4,5,6]
}
let str = 'Strive';
//let arr = str.split('');
let arr = Array.from(str);
console.log(arr);//["S", "t", "r", "i", "v", "e"]
let json ={
0:'apple',
1:'banana',
2:'orange',
length:3
};
let arr = Array.from(json);
console.log(arr);//["apple", "banana", "orange"]
上面这三个例子的__proto__都为Array
Array.of()
- 作用:把一组值转换为数组
let arr = Array.of('apple','banana','orange');
console.log(arr);//["apple", "banana", "orange"]
新增的数组的几个方法
- arr.find()
作用:找出第一个符合要求的数组成员,如果没有则返回undefined
let arr = [23,900,101,80,100];
let res = arr.find((val, index, arr) =>{
return val>1000;
});
console.log(res);//undefined
-
arr.findIndex()
作用:找出第一个符合要求的数组成员的位置,没找到则返回-1 -
arr.fill()
作用:对数组进行填充
//arr.fill(填充的东西, 开始位置, 结束位置);
let arr = [1,2,3,4];
arr.fill(0);//参数只有填充的东西则全部替换
console.log(arr);//[0,0,0,0]
let arr = [1,2,3,4];
arr.fill(0,2);//[1,2,0,0]
arr.fill(0,1,2);//[1,0,3,4]
console.log(arr);
//[开始的位置,结束的位置)左闭右开的区间
- arr.includes()
作用:与arr.indexOf相似,包含就返回true,不包含就返回false
对象简介语法及对象新增
对象简介语法
let name = 'Strive';
let age = 18;
let json ={
name, //name:name,
age, //age:age
/* showA:function(){
return this.name;
} */
showA(){
return this.name;
},
showB(){
return this.age;
}
};
console.log(json.showA(), json.showB());
对象扩展运算符
let {x,y,...z} = {x : 1,y : 2,a : 3,b : 3};
console.log(x,y,z);
- 可用来合并两个对象
let ab = { ...a, ...b };
// 等同于
let ab = Object.assign({}, a, b);
Object.is()
用法:用来比较两个值是否相同,与===基本一致但是有两处不同(+0不等于-0,NaN等于NaN)
如果下列任何一项成立,则两个值相同:
- 两个值都是 undefined
- 两个值都是 null
- 两个值都是 true 或者都是 false
- 两个值是由相同个数的字符按照相同的顺序组成的字符串
- 两个值指向同一个对象
- 两个值都是数字并且
- 都是正零 +0
- 都是负零 -0
- 都是 NaN
- 都是除零和 NaN 外的其它同一个数字
Object.is('foo', 'foo'); // true
Object.is(window, window); // true
Object.is('foo', 'bar'); // false
Object.is([], []); // false
var foo = { a: 1 };
var bar = { a: 1 };
Object.is(foo, foo); // true
Object.is(foo, bar); // false
Object.is(null, null); // true
// 特例
Object.is(+0, -0); // false
Object.is(NaN, 0/0); // true
Object.assign()
作用:用来合并对象
常见用途:
1.复制一个对象
2.合并参数
let json = {a:1};
let json2 = {b:2, a:2};
let json3 = {c:3};
let obj = Object.assign({},json,json2,json3);
console.log(obj);//{a:2,b:2,c:3}
用在数组上
let arr = ['apple','banana','orange'];
let arr2 = Object.assign([], arr);
arr2.push('tomato');
console.log(arr2);//["apple", "banana", "orange", "tomato"]
console.log(arr);//["apple", "banana", "orange"]
keys,values,entries
let {keys, values, entries} = Object;
let json = {
a:1,
b:2,
c:3
};
for(let key of keys(json)){
console.log(key);//a b c
}
for(let value of values(json)){
console.log(value);//1 2 3
}
for(let item of entries(json)){
console.log(item);//['a':1] ['b':2] ['c':3]
}
for(let [key, val] of entrires(json)){
console.log(key, val);
}
Promise
- 作用:解决异步回调的问题,Promise是一个对象
- Promise对象有三种状态:pendding(正在请求),rejected(失败),resolved(成功)
语法:
let promise = new Promise(function(resolve,reject){
//resolve 调用成功
//reject 调用失败
});
promise.then((res) => {//then中有两个参数,res对应resolve的回调,err对应reject的回调
},(err) => {
})
promise.catch((err) => {
})
- 简洁的写法:
new Promise().then((res) => {
}).catch((err) => {
})
//一般then只处理成功的,catch用来处理错误的,并捕获错误信息
只有promise内部状态发生变化then才会执行
示例:
let promise = new Promise(function(resolve,reject){
console.log('1');
});
promise.then((res) => {
console.log('2');
})
//只打印出了1
Promise.resolve()
作用:将现有的东西转换成一个Promise对象,并且是resolved状态
Promise.resolve('aa');
//等价于
new Promise(resolve => {
resolve('aa');
});
Promise.reject()
作用:用法与resolve一样,状态为rejected状态
Promise.all([Promise1],[Promise2],…)
作用:将任意个promise对象打包放在一个数组里面,只有这些promise对象状态都为为resolved状态,通过Promise.all()生成的对象的状态才为resolved状态,否则为rejected状态
Promise.race([Promise1],[Promise2],…)
作用:通过Promise.race()生成的对象的状态是,数组中先执行的那个Promise对象的状态
小示例:
let status = 1;
let userLogin = (resolve, reject) => {
setTimeout(() => {
if (status == 1) {
resolve({ data: '登录成功', msg: 'xxx', token: 'xxsadfsadfas' });
} else {
reject('失败了');
}
}, 2000);
};
let getUserInfo = (resolve, reject) => {
setTimeout(() => {
if (status == 1) {
resolve({ data: '获取用户信息成功', msg: 'asdfasdf', token: 'xxsadfsadfas' });
} else {
reject('失败了');
}
}, 1000);
}
new Promise(userLogin).then(res => {
console.log('用户登录成功');
return new Promise(getUserInfo);
}).then(res => {
console.log('获取用户信息成功');
console.log(res);
})
类-继承
ES5中的继承方式
- 普通的继承方式
//父类
function Father(name) {
this.name = name;
}
Father.prototype.showName function() {
return `名字是:${this.name}`;
}
//子类
function Son(name,age) {
Father.call(this,name);
this.age = age;
}
Son.prototype = new Father();
Son.prototype.showAge = function() {
return `年龄是:${this.age}`;
}
//调用
let person = new Son("qwe","12");
console.log(person.name,person.age);//qwe 12
console.log(person.showName());//名字是:qwe
- 圣杯模式实现继承
var inherit = (function (){
var F = function () {};
return function (Target,Origin) {
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constuctor = Target;
Target.prototype.uber = Origin.prototype;
}
});
ES6中实现的继承
class Father {
constructor(name) {
this.name = name;
}
showName() {
return `名字为:${this.name}`;
}
static showMale() {
console.log(`xxxxxx`);
}
}
class Son extends Father{
constructor(name,age){
super(name);
this.age = age;
}
showName() {
super.showName();//调用父类的方法
}
showAge() {
return `年龄是:${this.age}`;
}
}
let person = new Son("asd",34);
console.log(person.showName(),person.showAge());//名字为:asd 年龄是:34
console.log(Son.showMale());//xxxxxx
- 在子类中如果有函数名与父类一样的方法会重写父类的方法,通过super调用父类的方法后就不会重写,也可实现子类的方法。
- 在方法前面加static后这个方法不会被实例继承,子类可以继承该方法
小练习
对方快实现拖拽
<div id="div1" class="box left">DIV1</div>
<div id="div2" class="box right">DIV2</div>
class Drag {
constructor(id) {
this.div = document.querySelector(id);
this.disX = 0;
this.disY = 0;
this.init();
}
init() {
this.div.onmousedown = function(e) {
this.disX = e.clientX - this.div.offsetLeft;
this.disY = e.clientY - this.div.offsetTop;
document.onmousemove = this.Move.bind(this);
document.onmouseup = this.Up.bind(this);
return false;//阻止默认事件
}.bind(this);
}
Move(e) {
this.div.style.left = e.clientX - this.disX + 'px';
this.div.style.top = e.clientY - this.disY + 'px';
}
Up() {
document.onmousemove = null;
document.onmouseup = null;
}
}
//设置拖拽不能越界
class allDrag extends Drag{
Move(e){
super.Move(e);
if(this.div.offsetLeft <= 0){
this.div.style.left = 0;
}else if(this.div.offsetTop <= 0) {
this.div.style.top = 0;
}
}
}
new Drag("#div1");
new allDrag("#div2");
新增数据类型symbol
- js中的数据类型有:number、string、boolean、object、function、undefined、symbol
symbol是es6新增的一种数据类型,它表示的是唯一的值(该值永Symbol声明后就是唯一的)
symbol的理解和使用
- 定义:
let syml = Symbol('aaa'); //括号里面的'aaa'并不是syml存储的值,它只是Symbol的描述
console.log(syml);//Symbol(aaa)
- 注意:
1.即使Symbol()后面的描述是一样的,但仍然是两个不同的值
let a = Symbol('aaa');
let b = Symbol('aaa');
console.log(a === b);//false
2.Symbol不能new
3.symbol是一个单独的数据类型,就叫symbol
let a = Symbol('aaa');
typeof(a);//"symbol"
4.如果symbol作为key,使用for in 循环是无法访问的
let symbol = Symbol('aaa');
let json = {
a : '1',
b : '2',
[symbol] : '123'//作为对象属性的写法
};
for(let key in json){
console.log(key);
//1
//2
}
Symbol.for()
- Symbol.for()方法也是创建一个symbol类型,但是它与Symbol()不同,以下示例
let a = Symbol.for('aaa');
let b = Symbol.for('aaa');
console.log(a === b);//true
Symbol.for(‘aaa’)在创建的时候会先去全局寻找,看看有没有用Symbol.for()的方式,并且括号里面的内容为’aaa’来创建的值,如果没有则自己直接新建一个并且在全局登记,下次有另一个值也用Symbol.for(‘aaa’)来创建symbol类型的时候直接用已创建的。Symbol()则是直接创建一个symbol类型
Symbol.keyfor()
- Symbol.keyfor()就是返回Symbol.for()中的key值(即括号里面的内容)
let a = Symbol.for('aaa');
console.log(Symbol.keyFor(a));//aaa
generator、async
generator
- generator(生成器),整个Generator函数就是一个异步任务的容器,在需要暂停的位置使用yield语句
- 基本语法以及使用
function * show() {
yield '1';
yield '2';
return '3';
}
let a = show();
//a.next() //{value: "1", done: false}
//a.next() //{value: "2", done: false}
//a.next() //{value: "3", done: true}
当执行到return时done为true
- 使用for of可以自动遍历 generator,但是return后面的不会遍历
function * show(){
yield '1';
yield '2';
return '3';
}
let a = show();
for(let val of a){
console.log(val);
}
//1
//2
- 对generator函数也可以使用解构
function * show(){
yield '1';
yield '2';
yield '4'
return '3';
}
let [a,...b] = show();
console.log(a,b);//1 [2,4]
async
async写在函数前面表示这个函数是异步的
- async特点:
1.相比generator语义化更强
2.await后面可以是promise对象,也可以数字、字符串、布尔
3.async函数返回是一个promise对象
4.只要await语句后面Promise状态变成 reject, 那么整个async函数会中断执行 - 基本语法
async function fn() {
let result = await ...
}
- async函数返回一个Promise对象,async函数中return返回的值可以成为then方法回调的值
async function fn(){
return 'welcome';
}
fn().then(res=>{
console.log(res);//welcome
})
- async函数抛出的错误,catch方法额参数会接收这个错误
async function fn(){
throw new Error('Error出错了');
}
fn().then(res=>{
console.log(res);
}).catch(err=>{
console.log(err);//打印错误信息
})
- await后面的Promise对象状态为rejected会终止,函数里后面的代码不会运行
async function fn(){
await Promise.reject('出现问题了');
let a = await Promise.resolve('success');
console.log(a);
}
fn().then(res=>{
console.log(res);
}).catch(err=>{
console.log(err);
})
//出现问题了
解决出错问题的方法
//在awit后面的Promise对象后面通过catch的参数接收错误
async function fn(){
await Promise.reject('出现问题了').catch(err=>{
console.log(err);
});
let a = await Promise.resolve('success');
console.log(a);
}
fn().then(res=>{
console.log(res);
});
Set & Map
Set
- set数据结构类似于数组,但是里面不能有重复的值
- 注意:Set({a:1})这样使用是错误的,括号里面不能直接放对象,但可以通过add()方法进行添加
- 用法:
let a = new Set(['a','b']);
console.log(a);//{"a", "b"}
set数据结构的几种方法
- add() – 添加一项
该方法可以链式调用
let a = new Set(['a','b']);
a.add(1);
//a.add(1,2);//这样写也只会添加1进去
console.log(a);//{"a", "b", 1}
- delete() – 删除一项
let a = new Set(['a','b']);
a.delete('a');
console.log(a);//{'b'}
- has() – 判断里面有没有某个值
let a = new Set(['a','b']);
a.has('a');//true
- size – 个数
let a = new Set(['a','b']);
console.log(a.size);//2
- clear() – 清空
let a = new Set(['a','b']);
a.clear();
console.log(a);//{}
set数据结构的遍历
Set数据结构的key值和value值是一样的,遍历的时候默认遍历的是value
let setArr = new Set(['a','b','c','d']);
for(let item of setArr.keys()){
console.log(item);
}
console.log('---------------------------');
for(let item of setArr.values()){
console.log(item);
}
console.log('---------------------------');
for(let item of setArr.entries()){
console.log(item);
}
console.log('---------------------------');
for(let [k,v] of setArr.entries()){
console.log(k,v);
}
最好直接使用forEach进行遍历
let setArr = new Set(['a','b','c','d']);
setArr.forEach((value,index) =>{
console.log(value, index);
});
set的一些用处
- 可以通过扩展运算符…来实现数组去重
let arr = [1,2,3,4,5,6,7,6,5,4,3,2,1,2,3,4,4];
let newArr = [...new Set(arr)];
console.log(newArr);//[1, 2, 3, 4, 5, 6, 7]
- 通过…转化为数组后使用数组map方法
let set = new Set([1,2,3]);
set = new Set([...set].map(val=>val*2));
console.log(set);//{2, 4, 6}
WeakSet()
WeakSet()与Set基本一样,WeakSet()里面一般用来放对象
WeakSet()没有size,也没有clear()
Map
Map类似与json,但map的健(key)可以是任意类型
- 用法:
let map = new Map();
Map的一些方法
与set一样有delete、has、clear三种方法,用法也是一样。Map还有set,get方法
- set&get
let map = new Map();
let json = {
a:1,
b:2
};
map.set('a','aaa'); //正常
map.set(json, 'aaa');
map.set('aaa', json);
console.log(map.get(json));
console.log(map.get('aaa'));
- 对map进行遍历
let map = new Map();
let json = {
a:1,
b:2
};
map.set('a','aaa'); //正常
map.set(json, 'aaa');
map.set('aaa', json);
//循环
for(let [key,value] of map){
console.log(key,value);
}
WeakMap()
WeakMap()的key只能是对象
数字变化&Math新增
数字变化
- 二进制:
let a = 0b010101; - 八进制
let a = 0o666; - 十六进制
#ccc
Number上的方法
- Number.isNaN(NaN); -->true
- Number.isFinite(a) 判断是不是数字
- Number.isInteger(a) 判断数字是不是整数
安全整数
- 范围:[-(253-1),(253-1)]
- Number.isSafeInteger(a); -->判断是否为安全整数
Number.MAX_SAFE_INTEGER 最大安全整数
Number.MIN_SAFE_INTEGER 最小安全整数
Math的常用方法
Math.abs(x);//返回指定x的绝对值,传入一个非数字形式的字符串或者 undefined/empty 变量,将返回 NaN。传入 null 将返回 0。
Math.sqrt();//返回平方根,如果数值为负数则返回NaN
Math.sin();
Math.trunc();//截取,只保留整数部分
Math.trunc(4.5);//4
Math.trunc(4.9);//4
Math.sign(-5);//判断一个数到底是正数、负数、0
Math.sign(-5);//-1
Math.sign(5); //1
Math.sign(0); //0
Math.sign(-0); //-0
Math.cbrt() //计算一个数立方根
命名捕获
- 语法:(?<名字>)
let str = '2021-04-29';
let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
let {year, month ,day} = str.match(reg).groups;
console.log(year,month,day);//2021 04 29
- 反向引用命名捕获
语法:\k<名字>
let str = 'welcome-welcome';
let reg = /(?<name>welcome)-\k<name>/;
console.log(reg.test(str));//true
let reg = /^(?<name>welcome)-\k<name>-\1$/;
//匹配: 'welcome-welcome-welcome'
- 替换
let str = '2021-04-29';
let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
str = str.replace(reg,'$<day>/$<month>/$<year>');
console.log(str);//29/04/2021
- dotAll 模式 s
之前 ‘.’ 在正则里表示匹配任意东西, 但是不包括 \n,但是在dotAll模式下什么都可以匹配
let reg = /./s;
标签函数
调用的时候写法:fn参数
function fn(args){
console.log(args);//这里的参数是一个数组,第0项为welcome
return 1;
}
console.log(fn`welcome`);