ES6入门基础

935 阅读7分钟

一.什么是ES6?ES5、ES6和ES2015有什么区别?

ES6是新一代的JS语言标准,对部分的JS的语言进行了优化升级,规范了JS的使用标准,使得JS的使用更加的规范,更加优雅,更适合大型应用的开发。

S2015特指在2015年发布的新一代JS语言标准,ES6泛指下一代JS语言标准,包含ES2015、ES2016、ES2017、ES2018等。现阶段在绝大部分场景下,ES2015默认等同ES6。ES5泛指上一代语言标准。ES2015可以理解为ES5和ES6的时间分界线。

二.let和const命令

1.基本用法

ES6新增了let命令,用来声明变量,用法类似于var,但是所声明的变量只在let命令的代码块中有效。

for (let i = 0; i < 10; i++) {
  // ...
}

console.log(i);
// ReferenceError: i is not defined

上面循环中,i只在for循环中有效

{
  let a = 10;
  var b = 1;
}

a // ReferenceError: a is not defined.
b // 1

上面代码a只在它所在的代码块中有效

不存在变量提升

var变量会发生变量提升的现象,即变量可以在声明之前使用,值为undefined。 而let必须在变量声明之后使用,否则会报错。

// var 的情况
console.log(foo); // 输出undefined
var foo = 2;

// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;

暂时性死区

只要块级作用域内存在let命令,它所声明的变量就会绑定这个区域,不会受外部影响。

var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

ES6明确规定,在let声明之前,该变量都是不可用的,称作暂时性死区。

不允许重复声明变量

let不允许在相同作用域内,重复声明同一个变量。

// 报错
function func() {
  let a = 10;
  var a = 1;
}

//基本用法 报错
function func() {
  let a = 10;
  let a = 1;
}

2.块级作用域

块级作用域的作用 没有块级作用域,这会带来很多不合理的场景

  • 内层变量可能会覆盖外层变量
  • 用来计数的循环变量可能会泄露成为全局变量。

3.const命令

基本用法 一旦声明就不能,常量的值就不能被改变,而且声明之后必须立即对其初始化,否则会报错。

const foo;
// SyntaxError: Missing initializer in const declaration

const的作用域和let命令相同,只在声明的所在的块级作用域有效。用来保证声明的变量不会被改动。

##4.ES6声明变量的六种方法 ES5只有var,function,而ES6添加了let,const,import,class。

三.变量的解构赋值。

左右两边结构必须一样;右边合法;声明和赋值不能分开(必须在一句话里完成)

1.数组的解构赋值

基本用法

之前为变量赋值只能直接指定值

let a = 1;
let b = 2;
let c = 3;

而ES6 let [a, b, c] = [1, 2, 3];

let [foo, [[bar], baz]] = [1, [[2,3], 3]];
foo // 1
bar // 2,3
baz // 3

let [ , , third] = ["foo", "bar", "baz"];
third // "baz"

let [x, , y] = [1, 2, 3];
x // 1
y // 3

let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]

let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []

如果解析不成功,变量的值为undefined

let [foo] = [];
let [bar, foo] = [1];

这两种方式中foo的值都会为undefined;

默认值

解构赋值允许指定默认值。

let [foo = true] = [];
foo // true

let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'

2.对对象的解构赋值

变量必须与属性同名才能成功赋值

let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"

let { baz } = { foo: 'aaa', bar: 'bbb' };
baz // undefined

3.函数的扩展

函数参数的默认值(重点)

Es6允许为参数直接设置默认值,直接定义在参数的后面。

function log(x, y = 'World') {
  console.log(x, y);
}

log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello

函数的length属性:可以返回没有指定默认值的参数个数

(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2

rest参数:(形式...变量名)用于获取函数的多余参数,rest参数搭配的变量是一个数组,将变量多余的参数放入数组中。rest参数后不能再有其他参数。

function add(...values) {
  let sum = 0;

  for (var val of values) {
    sum += val;
  }

  return sum;
}

add(2, 5, 3) // 10

扩展符运算(形式...) 可以将一个数组拆开成若干参数。

console.log(...[1, 2, 3])
// 1 2 3

console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5

[...document.querySelectorAll('div')]
// [<div>, <div>, <div>]

箭头函数基本用法(重点)

基本用法

允许使用箭头来定义函数, 如果只有一个参数圆括号省略,若果还有一个return,{}可以省略

var f = v => v;

等同于

var f = function(v) {
  return v;
};

如果不需要或需要多个参数,可以用一个函数表示参数部分

var f = () => 5;
// 等同于
var f = function () { return 5 };

var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
  return num1 + num2;
};

箭头函数使用时需要注意的点

  • 函数体内的this对象,就是定义时所在的对象,不是使用时所在的对象。
  • 不可当做构造函数,不可以使用new命令。
  • 不可以使用arguments对象,可以用rest参数替换
  • 不可以使用yield命令,因此箭头函数不能用作Generator函数。

其中注意在箭头函数中,this的指向固定的,它的内部没有自己的this,这也就导致了this总是指向上一层的this,如果上一层还是箭头函数,则继续向上指,直到指向到有自己this的函数为止,并作为自己的this。

数组的扩展

  • map 映射
let arr=[12,5,8];
let result =arr.map((item)=>{
    return item *2;
})

let score=[19,85,99,25];
let result=score.map(item=>item>=60?'及格''不及格');

  • reduce 汇总,一堆出来一个,总数,平均数
let arr=[12,46,33,56];
//计算总和,temp表示的是中间结果,item一次遍历数组,index,循环次数
let num=arr.reduce(function(temp,item,index){
    return temp+item;
})
  • filter 过滤器,保留一部分,去留一部分
//留下3的倍数,留下返回true的部分  
let arr=[12,5,6,75,46];
let result=arr.filter(item=>{
    if(item%3==0)
        return false;
    else return true;
})
  • forEach 循环迭代

4.对象的扩展

  • 可以直接以变量形式声明属性或方法(传统的键值对形式)
let es5Fun = {
    method: function(){}
}; 
let es6Fun = {
    method(){}
}

5.Symbol是什么?有什么作用?

Symbol是ES6引入的第七种原始数据类型(说法不准确,应该是第七种数据类型,Object不是原始数据类型之一,已更正),所有Symbol()生成的值都是独一无二的,可以接受一个字符串作为参数,var s1=Symbol(); var s2=Symbol("foo"),可以作为属性名,而且并不是私有属性

let a={};
let name=Symbol();
a[name]='oll';

6.Promise对象

完成异步请求:多个任务同时进行,代码更复杂 形式:

let p=new Promise(function(resolve,reject){
    //resolve成功
    //reject失败了
    $.ajax({
        url:'arr.text',
        dataType:'json',
        success(arr){
            resolve(arr);
        }
        err0r(err){
            reject(err)
        }
        
    })
})
//promise 对象掉用then函数开始执行,then的第一个参数是resolve函数,第二个///参数是reject函数
p.then(function(){
    alert('成功了')
},function(){
    alert('失败了')
})

重点promise.all方法

function createPromise(url){
    return new Promise(function(reslove,reject){
        $ajax({
            url,
            dataType:'json',
            success(arr){
                resolve(arr)
            },
            error(err){
                reject(err)
            }
        })
        
    })
    
}


//多个Promise同时执行
Promise.all([p1,p2]).then(function(arr){
    console.log(arr);//ajax中传的内容但是内容都会放在arr中
    let [res1,res2]=arr;//利用解构赋值可以将结果分解出来
},function(){
    //一个失败就会返回失败的结果
})

代码优化

Promise.all([
$ajax({}),
$ajax({})
]).then(function(results){
    let[arr1,arr2]=result; 
},function(){
    //失败
})

7.async和await在干什么

解决异步问题,async返回的是一个Promise对象,await是在等待一个async函数完成,因为async函数返回的是一个Promise对象,await 必须出现在 async 函数内部,不能单独使用如果await函数等到了一个promise对象,await会阻塞后面的代码

举例:

//我们仍然使用 setTimeout 来模拟异步请求
function sleep(second, param) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(param);
        }, second);
    })
}

async function test() {
    let result1 = await sleep(2000, 'req01');
    let result2 = await sleep(1000, 'req02' + result1);
    let result3 = await sleep(500, 'req03' + result2);
    console.log(`
        ${result3}
        ${result2}
        ${result1}
    `);
}

test();
//req03req02req01
//req02req01
//req01

8.Proxy

  • 什么是Proxy? 是ES6中提供的一个构造函数,更像一种拦截器,在访问赋值时会先用到我们定义好的拦截方法。

  • 为什么需要Proxy()?别代理对象不希望直接别访问;被代理的对象能力不足时找个人帮他做,增加新的功能

  • Proxy的用法? Proxy的构造函数中接受两个参数new Proxy(target,hander)其中target参数是指目标对象(被代理的的对象),一个对象,属性是各种控制和修改target基本方法的行为。

举例:用户未设置头像返回默认头像

const user={name="cz"};
const userProxy=new Proxy(user,{
    get:(obj,prop)=>{
        if(prop==='avatar'){
            if(!obj.prop){
                return 'https://...'
            }
        }
        return obj[prop];
    }
})

9.Generator函数

  • 什么是Generator()? 执行到中间可以停,配合yield函数使用
  • 作用:可以实现带逻辑的异步
//注意声明方式比较特殊有个*
function *show(){
    alert('a');
    
    yield;//控制在哪里停
    
    alert('b');
} 
//使用起来也比较特殊
let genodj=show();

genobj.next();//开始执行,打印a,碰到yield停下来

genobj.next();//打印出b

yield既可以传参,也可以返回。

function *show(){
    alert('a');
    
    let a=yield;//控制在哪里停,可以有返回值,此时a的值为5
    
    alert('b');
} 
//使用起来也比较特殊
let genodj=show();

genobj.next(12);//

genobj.next(5);//
runner(function*(){
    let data1=$.ajax({url:,dataType});
    let data2=$.ajax({url:,dataType});
    let data3=$.ajax({url:,dataType});
})