ES6
let和const
- let
- let声明的变量不进行变量提升
- let声明的变量在同一个作用域下不能重名
- 代码执行之前,会进行过滤如果重名就会报错 (全局代码执行之前,函数即使不执行函数里也进行过滤如果重名就会报错)
- let声明的变量只在当前作用域有效(能往上级作用域查找)
- let可以解决暂时性死区
- const
- 定义常量:不可以被修改
- const定义常量必须赋值
- let和const没有变量提升,var有变量提升
- let和const不能重复声明,var可以
- var在全局作用域下声明变量会给window增加键值对,let不会
暂时性死区
// console.log(a)
// console.log(typeof a) // 'undefined'
// var a=12;
console.log(typeof a)//Cannot access 'a' before initialization
//无法在初始化之前访问'a'
let a = 12
// ES6让js变得更加严谨
块级作用域
- if else for while try catch -->块级作用域
- 块级作用域,和形参重名,函数赋值不能影响外面
- 在块级作用域下var和function是不可以重名的
//
console.log(num);// undefined
console.log(fn);// undefined
if([]){
// 只要进到当前if条件中,会立即对fn进行赋值;
// 支持es6的浏览器,会把这个if的大阔号解析成一个块级作用域;
fn()
var num=100;
function fn(){console.log("a")}
}
console.log(fn);//fn(){console.log("a")}
//
console.log(fn);// undefined
for(var i=0;i<2;i++){
function fn(){}
}
console.log(fn);//function fn(){}
//
console.log(f); //undefined
let i = 0;
while (i < 1) {
i++
function f() {
}
}
console.log(f); //function fn(){}
- 块级作用域,和形参重名,函数赋值不能影响外面
var b = {
a: "hello"
};
function fn(b) {
b.a = "world";
if (true) {
function b(){}//块级作用域,和形参重名,函数赋值不能影响外面
}
console.log(b);//{a: "world"}
}
fn(b)
- 在块级作用域下var和function是不可以重名的
// 在块级作用域下var和function是不可以重名的
if (!("aa" in window)) {
var aa = 1;
function aa() {
console.log(aa)
}
}
console.log(aa);//报错Identifier 'aa' has already been declared 已声明标识符“aa”//
for循环
- for循环;let定义的变量位置是一个父作用域,每一轮循环都是一个子作用域;每一个子作用域不会销毁,并且每一个子作用域存储了变量i;
箭头函数
- 箭头函数没有this
- 箭头函数没有this,要是在箭头函数里使用this,就看他上一级作用域的this,【上一级作用域中this是谁,箭头函数中this就是谁】,不能用call更改,不能被new
- 不能被new,没有prototype属性,不可以作为构造函数。
- es6规定箭头函数就是函数,class就是类,箭头函数不能作为类
- 箭头函数中没有arguments,用剩余运算符代替
- 给函数的形参赋默认值(普通函数和箭头函数都可以)
- 箭头函数不能作为generator函数;
- 写法
- 如果只有一个形参,可以去掉小括号
- 如果只有return一行代码可以省略return和大括号
- 如果return的是一个对象你要是省略的话,就给对象加小括号
// let m;
// const y;
// =====================================================
// let fn = () => {
// console.log(this)
// }
// fn()
// let obj = {
// name:3,
// fn:function(){
// // this->obj
// return ()=>{
// console.log(this)
// }
// }
// }
// obj.fn()()
// let fn = (w)=>{
// return {name:3}
// }
// let fn1 = w=>({name:3})
// console.log(fn1())
// 箭头函数
// 1.箭头函数形式
// 1. 在()和{}之间换成了=>,去掉了function;
// 2. 如果箭头函数中只有一个形参,可以省略小括号
// 3. 如果{}只有一条语句可以省略大括号;
// 4. 如果箭头后面只有一个值,这个值就是函数的返回值;省略了{}和return;
// 5. 如果返回一个对象,并且去掉{}和return,需要在对象的外面加上();
// 2.箭头函数执行
function f(){}
var fn = function(num){}
fn()
let f = num =>({num});
var d = f(1)
console.log(d);
function fn(a) {
return function (b) {
return function (c) {
return a + b + c;
}
}
}
let fn = a => b => c => a + b + c;
fn(1)(2)(3)
class的语法(class自定义类)
// function Fn(){
// };
//let fn=()=>{};// 不能作为构造函数;
// class : class 类名 {}
// var a = 1;
// var obj = {
// a,
// fn(){// 这不是一个箭头函数;
// console.log(100);
// }
// }
// obj.fn();
// console.log(obj);
class Bar{ // 这既不是一个函数的{},也不是对象的{};
constructor(x,y){
// 这个的代码就相当于函数体中的代码;
// 这里面可以新增实例私有属性
//this.x=x;
this.y=y;
}
// 在原型上新增方法;
getX(){// 这不是箭头函数
console.log("X");
}
getY(){
console.log("Y");
}
static x=1// static可以给Bar类新增私有属性
y=2// 在给实例新增私有属性
}
console.log(typeof Bar)
//Bar.prototype.x=100;
console.dir(Bar);
let a = new Bar(100,200);
console.log(a);
// {x:1,arguments:null,caller:null,prototype:{}}
// Bar
// console.log(a);
//var b = Bar();
//console.log(b);
// function Fn(){
// var num=1;
// // this.x=num;
// }
// Fn.prototype.getX=function(){
// }
// Fn.x=1;//
// let f = new Fn;
// console.log(f.x)
// function Fn(){
// this.s = 5;
// }
// Fn.prototype.getX = function(){
// }
// Fn()
// new Fn
class Fn {
// 这里边放的是实例的私有属性
constructor (n,m){
this.s = n
}
// 直接在外边写就是给实例添加公有属性
getX(){
console.log(111)
}
r = 4 // 如果用等号赋值,那就是给实例增加私有属性
static m = 10 // 把Fn当做对象,增加键值对
}
Fn.prototype.getY = function(){console.log(222)}
let f = new Fn(3);
// Fn() 报错
console.log(f)
console.log(Fn.prototype)
console.dir(Fn)
class继承
// ES6中class创造出来的类不能当做普通函数执行
class A {
constructor(q) {
this.x = q;
}
getX() {
console.log(this.x)
}
}
// ES6中的继承
class B extends A {
constructor(name) {
// 子类继承父类,可以不写constructor,但是你要是一旦写了,
那在constructor里第一句话就要写super()
// 你要是不写constructor,那浏览器会默认创建一个constructor(...arg){
// super(...arg)
// }
super(200) // A.call(this, 200) 把父类当做普通函数执行,给方法传递参数,
让方法中的this是子类的实例
this.y = 100;
}
getX() {
console.log(this.y)
}
}
B.prototype = Object.create(A.prototype); // class定义的类不能改原型重定向
let f = new B(100);
console.log(f)
-----------------------------------------------------------
//class继承
class A{
constructor(){
this.x =1;
}
getX=()=>{
// 这是一个普通函数
}
getY(){
// 这是一个公有的属性
}
}
let a = new A;
// B的prototype中的__proto指向A的原型
// class 继承既继承A的私有属性,又能继承其公有属性;
class B extends A{
constructor(a){
super();// super;
this.z=a;
}
getZ(){
}
}
let b = new B(1);
console.log(b);
普通对象
- 普通对象里的属性名和属性值一样时,只写一个就可以。
{
name,
age,
sex
}
函数参数
- 在ES6中,形参可以被赋默认值;
- 如果有实参,并且不是undefined,那么实参会将默认值覆盖;
- 如果使用函数默认值时,在此上下文中不允许重复参数名
function fn(x,y={}){
console.log(x,y);
}
fn("a",null);
------------------------------------------
// 如果使用函数默认值时,不允许有重名的参数
function fn(x,x,y=1){
console.log(x);//Duplicate parameter name not allowed in this context
//在此上下文中不允许重复参数名
}
fn(1,2,3)
解构赋值
- 在ES6中,按照一定的模式,从数组或对象中给变量赋值
- 在数组中,解构是一一对应的;如果只有变量,右边没有对应的值,那么默认解构出undefined
- 被解构的值一定是可遍历的
let [a,b,c,d]=[100,200,300];
console.log(a)//100
console.log(b)//200
console.log(c)//300
console.log(d)//undefined
let a=1;//报错
- 解构赋值允许赋默认值
let [a,b=1]=[1]
console.log(b)//1
对象的解构赋值
- 对象是按照对象的属性名进行匹配和解构的,必须保持属性名一致
- 如果等号右边没有对应的属性值,解构出undefined
- 如果右面严格等于undefined,那么存储默认值
let {name,age}={name:"zhufeng",age:10};
console.log(name)//"zhufeng"
function fn(){}
//fn就是属性名,就是fn;右边是属性值,fn所代表的值;
//如果属性名和属性值相同可以省略一个
var obj={fn}
-------------------------------------------
var obj = {
a: {
}
}
let {
a:n //n是别名,只能拿到属性值
} = obj;
console.log(n);
字符串的解构赋值
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
函数的参数解构赋值
- 参数的解构:如果有实参,那么实参的值一定覆盖默认的值
- 如果没有实参,形参也没有对应的要解构的值,这样就会报错
- 如果没有实参,形参有对应的要解构的值,那么会进行解构默认的对象
function fn([x,y]){
console.log(x)
console.log(y)
}
fn([1,2])
-----------------------------------
function move({
x,
y
}) {
return [x, y];
}
console.log(move({
x: 3,
y: 8
}));// [3, 8]
…运算符
- 收缩运算符(一般用在函数的形参)
- 展开运算符(一般用在函数的实参)
- 拓展运算符
// ...运算符
// function fn(...g){
// console.log(g)
// }
// fn(...[12,34,46,67,78,132,32,34])
// let ary = [12,23,45,66];
// // let n = ary[0]
// // let m =[]
// // 前提是等号的左边和右边结构的一样
// let [m,...a] = ary;
// console.log(m,a) // 12 , [23, 45, 66]
// // 我想拿到数组的第一项和最后一项
// // let [x,,,s] = ary;
// console.log(x,s)
// let ary = [12,234,45,[23,435]];
// console.log(ary[3][1]) // 435
// let [m,,,[,x]] = ary
// console.log(m,x) // 12, 435
// 普通对象的解构赋值
// let obj = {
// name:2,
// age:3
// }
// let obj1 = {...obj}
// console.log(obj1) // 克隆obj
// 在左边的对象里定义变量名,如果这个变量名在右边的对象里有对应的属性名,
那就把对应的属性值赋值给左边的变量名.
// 如果右边没有这个属性名就是undefined
// 还可以给左边的变量赋默认值
// let {name,age,we = 9} = obj;
// console.log(name, age,we);
// let ary = [1,2,3];
// let [m, , , r = 6] = ary
// console.log(m,r)
// let obj = {
// name:3,
// age:4
// }
// // name:haha
// // 创建一个haha变量名,把name对应的值赋值给他
// let {
// name:haha
// } = obj
// console.log(haha)
let obj = {
name:'erYa',
age:18,
friends:['xioaHua', 'gouDan']
}
let {friends:[,s]} = obj
console.log(s) // 'gouDan'
扩展运算符
可以将对象展开,也可以将数组展开
let arr=[12,2,3,45]
let ar1r=[120,200,300,450]
console.log(arr.concat(arr1))
console.log(...arr,...arr1)
var obj={name:100}
var obj1={age:200}
console.log({...obj,...obj1})
剩余运算符
//放到参数位置,只能作为最后一个形参
function sum(m,...ary){//将多余的值收缩成一个数组
console.log(m)
console.log(ary)
}
sum(10,2,3,4,5,7)
Set数据结构
- Set 是一种数据结构,不是一种数据类型;
- Set 数据中不能有重复的值;
- Set 是一个构造函数;
- Set传入的实参必须是可遍历的结构;数组 类数组 对象;
- Set实现数组去重
// 数组去重
// var ary=[12,45,66,34,56,34,45];
// let s = new Set();
// // 向set数据结构中加值;
// s.add(100);
// s.add(100);
// console.log(typeof s);// "object"
// console.log(s);
// 数组去重 12种
// Set传入的实参必须是可遍历的结构;数组 类数组 对象;
// var ary=[12,45,66,34,56,34,45];
// let s = new Set(ary);
// console.log(s);
// add
// delete
// has :是否含有某一个set成员,返回布尔值
// clear: 清空set成员;
Map数据结构
const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content')
m.get(o) // "content"
m.has(o) // true
m.delete(o) // true
m.has(o) // false
------------------------------
const map = new Map([
['name', '张三'],
['title', 'Author']
]);
map.size // 2
map.has('name') // true
map.get('name') // "张三"
map.has('title') // true
map.get('title') // "Author"
函数
generator函数
<script>
// generator函数:状态机
// 1.function 和函数名之间有一个*;
// 2.函数体内部使用了yield表达式,来定义函数体内部的状态;
// generator 函数是分段执行的,yield是暂停的标记,next是恢复执行;
function* fn(){
console.log(100);
yield "hello";
console.log(200);
yield "world";
console.log(300);
return 600;
}
let f = fn();// fn的返回值是一个指向指针的对象
let f1=f.next();// 让当前的状态切换到下一个指针
console.log(f1);// {value: "hello", done: false}
let f2 = f.next();
console.log(f2);
let f3 = f.next();
console.log(f3);
let f4 =f.next()
console.log(f4);
100
VM262:11 {value: "hello", done: false}
VM262:4 200
VM262:13 {value: "world", done: false}
VM262:6 300
VM262:15 {value: 600, done: true}
VM262:17 {value: undefined, done: true}
</script>
async函数
- async 函数会自动返回 promise
- try catch 包裹await函数 捕获到需要重新 throw e 抛出去,不然认为没有异常
<script>
// generator *=>async yield => await
// async函数: 有内置的执行器;
// async : 函数中有异步的操作;async函数默认返回一个promise实例
// await : 等待紧跟在后面的表达式需要等待的结果;
// await 下面代码是异步的;并且是一个微任务;await后面跟着代码是同步的;
// 异步任务分为宏任务和微任务;当主任务队列执行完成,需要执行异步任务,
异步任务先找到里面的微任务,按顺序执行,微任务执行完成,再去执行宏任务;
// setTimeout(()=>{
// console.log(300);
// },0)
// function fn1(){
// console.log(100);
// return 100;
// }
// async function fn(){
// let s = await fn1();
// console.log(s);
// console.log(200);
// }
// let result = fn();
// console.log(result);
function fn1(){
// 当函数中返回一个promise实例时
return new Promise(function(resolve,reject){
resolve("放假了");
})
}
function fn2(){
return new Promise(function(resolve,reject){
resolve();
})
}
async function fn(){
let s = await fn1();
// 1.如果fn1中返回一个promise实例,那么await下面的代码都是fn1中返回的promise实例then的
成功回调中的代码;
// 2.await函数的返回值s就是上一个promise实例中resolve传递的实参;
console.log(s);
console.log(200);
let a = await fn2();
console.log(666);
}
fn();
// 异步的请求
function getData(url){
return axios.get(url);
}
async function fn(){
// 将异步的代码变成同步;
let data= await getData("/list");
for(let i =0;i<data.length;i++){
}
}
</script>
引用数据类型
类数组转数组
Array.from
- 将类数组集合转成数组(元素集合,arguments)set和map的数据结构
Array.from 将类数组集合转成数组(元素集合,arguments)set和map的数据结构
function s(){
// let a=Array.from(arguments)
// console.log(a)
let a=[...arguments]
console.log(a)
}
s(1,2,3,4)
Array.of
将一组数转成数组
var a=Array.of(1,2,3)
console.log(a)
Object.assign()的用法
- Object.assign方法用来将源对象(source)的所有可枚举属性,复制到目标对象(target)。它至少需要两个对象作为参数,第一个参数是目标对象,后面的参数都是源对象。
let targetObj1 = { a: 1 };
let sourceObj1 = { b: 1 };
let sourceObj11 = { c: 3 };
Object.assign(targetObj1, sourceObj1, sourceObj11);
console.log(targetObj1);
--------------------------------------
function anonymous(content = '', options = {}) {
//=>参数初始化
/*
Object.assign方法用来将源对象(source)的所有可枚举属性,复制到目标对象(target)。它至少需要两个对象作为参数,第一个参数是目标对象,后面的参数都是源对象。
*/
options = Object.assign({
title: '系统温馨提示',
confirm: false,
handled: null
}, options);
return new Dialog(content, options);
}
ES5 数据拦截(Object.defineProperty)
//Object.defineProperty 劫持对象中某个属性的操作;
//全局变量也是给window设置一个全局属性
// var i=0;
// Object.defineProperty(window, "a", {
// get() {
// //获取window.a的时候触发
// return ++i;
// },
// set() {
// //给window.a设置属性值得时候触发
// console.log(2);
// }
// })
// if (a == 1 && a == 2 && a == 3) {
// console.log("ok");
// }
defineProperty
对一个对象的某个属性的定义
// Object.defineProperty:对一个对象中某个属性的定义(处理)
let obj = {
name: 'ls',
age: 10
};
// 设置属性的 GETTER、SETTER:我们可以在 GETTER、SETTER 中监听当前属性设置和获取的时候干什么 =>
// 这也是VUE 2.0 响应式数据(双向数据绑定)实现的原理,VUE 3.0采用的是 PROXY
Object.defineProperty(obj, 'name', {
get() {
console.log('GETTER');
return 'HELLO WORLD';
},
set(value) {
console.log('SETTER', value);
}
});
// console.log(obj.name);
obj.name = '哈哈哈~~';
//
Object.defineProperty(obj, 'name', {
value: '哈哈哈哈哈',
// 是否允许当前的属性被删除
configurable: true,
// 是否为可枚举的属性
enumerable: true,
// 是否允许当前属性被修改
writable: true
});
es6 数组实例的 fill()
fill方法使用给定值,填充一个数组。
fill方法用于空数组的初始化非常方便。数组中已有的元素,会被全部抹去。
fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置
['a', 'b', 'c'].fill(7)
// [7, 7, 7]
new Array(3).fill(7)
// [7, 7, 7]
['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']
字符串
模板字符串(``)
// let ss = 25;
// let str = '<li>'+ss+'</li>';
// '<li><span>'+ss+'</span><span>'+ss+'</span></li>'
// let str = `<li><span>${ss}</span><span>${ss}</span></li>`
实例方法:padStart(),padEnd()
- ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。
padStart()
用于头部补全,padEnd()
用于尾部补全。
'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'
- 如果省略第二个参数,默认使用空格补全长度。
'x'.padStart(4) // ' x'
'x'.padEnd(4) // 'x '
- 用来补零