es6

es6是ECMAScript的第六次修订,于2015年完成,也叫ES2015。

特点:语法上更加简洁,提高开发效率。

一、箭头函数

(当要求动态上下文的时候就不能够用箭头函数)

特点:

1、箭头函数中,this的指向是定义时所在的作用域对象,而非运行时;

2、不能够用作构造函数,即不能使用new命令;

2、不能够用arguments对象;

3、不能使用yield命令;

附:超时调用的代码都是在全局作用域中执行的,即setTimeOut中的this指向window,但是使用箭头函数可以改变this的指向.

 

二、var 、let 、const区别

var 有变量提升、没有块级作用域

let和const没有变量提升,一定要先声明再使用,有块级作用域,

let定义变量;const定义常量;

const定义后,不能修改其指向的目标,若是对象、数组,可以修改里面的属性值。我们可以在引用第三方库的时,把需要声明的变量,用const来声明,这样可以避免未来不小心重命名而导致出现bug .

const xxx = require('xxxxx'); 

 

var oLi=document.querySelectorAll('li')
var arr=[];
for(var i=0;i<oLi.length;i++){
    oLi[i].onClick(function(index){
        console.log(index) //打印出来的是3 
    });
}
,
//var定义的i为全局变量,每循环一次,新值都会覆盖旧值
//let 定义的i为局部变量,没循环一次,都为i创建新的绑定代码

//闭包


function show(i){
    return function(){
        console.log(i) //0、1、2
    }
}

var arr=[];
for(var i=0;i<3;i++){
   oLi[i].onClick(show(index));
}


//立即执行函数
for(var i=0;i<3;i++){
    (oLi[i].onClick(function(index){
         console.log(index)
    }))(i);
}
//0/1/2 //立即执行函数给每个 li 创造一个独立作用域

三、Set数据结构 、Map

Set是一个构造函数,类似数组,里面的值是唯一的;Set没有length属性值,遍历只能用for of

//数组去重:
let set=new Set([1,2,3,3]);
console.log([...set]) //[1,2,3]
console.log(Array.from(set)) //[1,2,3]
类数组转换为数组:
Array.prototype.slice.call(likeArray)//利用slice的返回新数组以及call改变this指向而形成一个新数组

类数组:(类似于一个数组的对象):是一个对象,里面有数组的值以及相应的属性(length).

类数组是指在写法上跟数组一样,比如argumens,函数的第一个参数是argument[0],写法上跟数组一样,但是不是数组,他的原型是Object。

常见的类数组有:

1、函数的参数 arguments,

2、DOM 对象列表(比如通过 document.querySelectorAll 得到的列表)

3、 jQuery 对象 (比如 $(“div”)).

Map与对象:

1、对象的key只能是字符串,Map的key可以是任意数据类型;

2、Map有自己的操作方法:

set是数据重组,map是数据存储

 

default默认值、rest

//不传参数的情况下,type为'cat'
function animal(type = 'cat'){
    console.log(type)
}
animal()

rest参数(形式为“…变量名”),用于获取函数的多余参数

//es5
function fn(){
    for(var i = 0; i<arguments.length ; i++){
        console.log(arguments[i]);
    }
}
fn(1,2,3);//1,2,3

//es6
function newFn(...args){
    args.filter((obj)=>{console.log(obj)})
}
newFn(1,2,3);//1 2 3

四、模板字符串

用反引号来拼接

`hello ${name}`

 

五、class、extend、super

Class是定义类的方法,es5用构造函数定义类,es6用class,让对象原型的写法更清晰、更面向对象编程的语法、更通俗易懂。

用class关键字定义一个类对象,这个类的构造器(constructor)和原型方法都放在这个对象里。

//es5 构造函数
function Person(name,age){
    this.name=name;
    this.age=age;
    
}
//原型方法
Person.prototype.getName=function(){
     rturn this.name;
}

//es6
class Person{
    constructor(name,age){ //构造函数,私有的
        this.name=name;
        this.age=age;
    }
    getName(){ //原型方法,共享的
        rturn this.name;
    }
     static getGender(){ //静态(私有方法)
        return this.gender;
    }
}
//继承
class Student extends Person{
    constructor(name,age){
        super(name,age); //相当于 Person.call(this),初始化this,子类的this继承父类的this
        //super就是父类的constructor,执行super()即调用父类构造函数,之后才会有this
        this.gender=gender;
        this.sex=sex;
    }
     getName(){ //原型方法,共享的
        super.getName();
         //super指向父类的原型
    }
    static getGender(){ //静态(私有方法)也可以继承
        super.getGender();
        //super指向父类本身
    }
}

class定义一个类时,不存在变量提升,为了方便继承,先声明子类,再声明父类。

//ES5可以先使用再定义,存在变量提升
new A();
function A(){

}
//ES6不能先使用再定义,不存在变量提升 会报错
new B();//B is not defined
class B{

}

 

五、promise

1、什么是promise?
回调地狱:由于javascript是单线程的,通常我们实现异步编程时就会用到回调函数,但是在某些场景下,会使用一次又一次的回调,最后会发现代码会变成金字塔状,这就称为回调地狱。

回调地狱的特点:可读性差、难以维护、难以捕获异常。

异步编程的另一种解决方法:promise

promise构造函数是同步执行的,then方法是异步执行的

名称:

承诺,表达了将来会执行的操作,代表异步操作

状态:

pending:进行中

fulfilled:已成功

rejected:已失败

过程:pending=>fulfilled,pending=>rejected(此时进入catch)

特点:

1、只有异步操作可以决定当前处于的状态

2、一旦状态改变就不会再变

const promise=new Promise(resolve,reject)=>{
    if(success){
        resolve(value)
    }else{
        reject(error)
    }
}
promise.then(()=>{
    //success
},()=>{
    //failed ,这个函数不是必须的
});
reject和catch的区别:

reject用来抛出异常,catch用来处理异常。

reject后的结果会进入then的第二个回调,如果没有第二个回调,则会进入catch

 

封装一个ajax的promise的简易版本
let ajax=function(url,data,type='post'){
    return new Promise((resolve,reject)=>{
        $.ajax({
            url:url,
            data:data,
            type:type,
            success(res){
               resolve(res) 
            },
            fail(res.statusText){
                reject(res.statusText)
            }
        });
    });
}
ajax('http:.....',{name:'',phone:1223352}).then((res)=>{
    //success
}).catch((error)=>{
    
});
//链式操作
ajax.then(success,fail).then(success,fail)
方法:
Promise方法:

1、Promise.prototype.then(()=>{console.log('resolve')},()=>{console.log('reject')}) // Promise实例状态改变时的回调

2、Promise.prototype.catch() //发生错误时的回调

3、Promise.all() //只有等数组所有的状态都变成fulfilled,Promise的状态才会变成fulfilled,此时会返回一个数组,传递给Promise的回调函数。若有一个为rejected,则进入reject或者catch回调

// 生成一个Promise对象的数组
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
  return getJSON('/post/' + id + ".json");
});当数组所有

Promise.all(promises).then(function (posts) {
  // ...
}).catch(function(reason){
  // ...
});

4、Promise.race() //谁先执行完成就先执行回调。先执行完的不管是进行了race的成功回调还是失败回调,其余的将不会再进入race的任何回调。

const pro1 = new Promise((resolve,reject) => {
    setTimeout(resolve,100,'1');
});

const pro2 = new Promise((resolve,reject) => {
    setTimeout(resolve,200,'2');
});

const pro3 = new Promise((resolve,reject) => {
    setTimeout(resolve,300,'3');
});

const pro4 = new Promise((resolve,reject) => {
    setTimeout(resolve,10,'4');
});


Promise.race([pro4,pro1,pro2,pro3]).then(data => {
    console.log(data);  // 1   输出最快的那个
}).catch(err => {
    console.log(err);
})

5、Promise.resolve() | Promise.reject() //将现有对象转为 Promise 对象,并手动改变状态

const p_1 = Promise.resolve('success');

p_1.then(data => {
    console.log(data);   // success
})

const p_2 = Promise.reject('err');

p_2.then(data => {
    console.log(data);  
}).catch(err => {
    console.log(err);  // err
})

 

六、模块化

1、函数封装、立即执行函数等,解决全局变量污染,防止模块内部的属性和方法被外部修改。

2、commonJS:通用模块规范,一个单独的文件就是一个模块,模块内部的变量无法被外部读取,但是commonJS是同步的,主要用于服务器。

3、AMD(预加载)/CMD(懒加载)异步模块加载,require方式。

4、js原生支持的模块加载方式:import(引入)、export(导出)

 

七、setTimeout、Promise、Async/Await 的区别

进程和线程:

进程:cpu资源分配的最小单位(系统给它分配内存)

线程:一个进程包含一个或多个线程,分别处理不同的事务;

浏览器是多进程的:Browser进程、第三方插件进程、GPU进程、渲染进程(浏览器内核)

其中浏览器内核(渲染进程)是多线程的:

1、GUI渲染线程

2、js引擎线程

3、事件触发线程

4、定时触发器线程

5、异步http请求线程

 

同步和异步:

同步:

异步:setTimeout、setInterVal、ajax、onClick事件

因为js引擎是单线程的,同一时间只能做一件事。为了提高效率,js把所有任务分为同步任务和异步任务,同步任务可以直接进入主线程执行,对于一些需要等待一段时间才会有结果的操作,把它放到任务队列当中,当它有结果之后就会通知主线程,然而只有等主线程有空闲的时候,才会把它放入主线程执行。

 

事件循环机制:

宏任务:script 、setTimeout、setInterval 、setImmediate 、I/O 、UI rendering

微任务:Promise.then()或reject()、Promise为基础开发的其它技术,比如fetch API、V8的垃圾回收过程、Node独有的process.nextTick。

js执行过程中同步代码直接执行,宏任务进入宏任务队列,微任务进入微任务队列。它每次只能执行一个任务,先执行宏任务,在执行过程中遇到微任务,就会把微任务放到微任务的事件队列当中,当一个宏任务执行完毕后,就会依次执行当前的微任务,微任务执行完毕,GUI线程开始渲染,渲染完毕,js引擎线程继续接管,执行下一个宏任务。

注意⚠️:在所有任务开始的时候,由于宏任务中包括了script,所以浏览器会先执行一个宏任务,在这个过程中你看到的延迟任务(例如setTimeout)将被放到下一轮宏任务中来执行。

async function async1() {
    console.log('async1 start');
    await async2();
    console.log('asnyc1 end');
}
async function async2() {
    console.log('async2');
}
console.log('script start');
setTimeout(() => {
    console.log('setTimeOut');
}, 0);
async1();
new Promise(function (reslove) {
    console.log('promise1');
    reslove();
}).then(function () {
    console.log('promise2');
})
console.log(script end)

script start=>async1 start=>async2=>promise1=>script end=>promise2=>setTimeOut

//1、首先,new Promise是同步的任务,会被放到主进程中去立即执行。而.then()函数是异步任务会放到异步队列中去,那什么时候放到异步队列中去呢?当你的promise状态结束的时候,就会立即放进异步队列中去了。
//2、带async关键字的函数会返回一个promise对象,如果里面没有await,执行起来等同于普通函数;如果没有await,async函数并没有很厉害是不是
//3、await 关键字要在 async 关键字函数的内部,await 写在外面会报错;await如同他的语意,就是在等待,等待右侧的表达式完成。此时的await会让出线程,阻塞async内后续的代码,先去执行async外的代码。等外面的同步代码执行完毕,才会执行里面的后续代码。就算await的不是promise对象,是一个同步函数,也会等这样操作

八、some、every、find、filter、map、forEach有什么区别

10、forEach()

    forEach():对数组进行遍历循环,对数组中的每一项运行给定函数。这个方法没有返回值。参数都是function类型,默认有传参,参数分别为:遍历的数组内容;第对应的数组索引,数组本身。

    var arr = [1, 2, 3, 4, 5];
    var a=arr.forEach(function(x, index, a){
    console.log(x + '|' + index + '|' + (a === arr));
    });
    console.log(a)
    // 输出为:
    // 1|0|true
    // 2|1|true
    // 3|2|true
    // 4|3|true
    // 5|4|true
    //  undefined

    11、map()

    map():指“映射”,对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。

    下面代码利用map方法实现数组中每个数求平方。

    var arr = [1, 2, 3, 4, 5];
    var arr2 = arr.map(function(item){
    return item*item;
    });
    console.log(arr2); //[1, 4, 9, 16, 25]

    12、filter()

    filter():“过滤”功能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组。

    var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    var arr2 = arr.filter(function(x, index) {
    return index % 3 === 0 || x >= 8;
    }); 
    console.log(arr2); //[1, 4, 7, 8, 9, 10]

    13、every()

    every():判断数组中每一项都是否满足条件,只有所有项都满足条件,才会返回true。

    var arr = [1, 2, 3, 4, 5];
    var arr2 = arr.every(function(x) {
    return x < 10;
    }); 
    console.log(arr2); //true
    var arr3 = arr.every(function(x) {
    return x < 3;
    }); 
    console.log(arr3); // false

    14、some()

    some():判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回true。

    var arr = [1, 2, 3, 4, 5];
    var arr2 = arr.some(function(x) {
    return x < 3;
    }); 
    console.log(arr2); //true
    var arr3 = arr.some(function(x) {
    return x < 1;
    }); 
    console.log(arr3); // false

 

posted @ 2020-04-13 11:43  2350305682  阅读(202)  评论(0编辑  收藏  举报