es6常用的语法(一)

1、 let和const命令

es5只有全局作用域和函数作用域,没有块级作用域。
下面看一个例子:

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

对于有块级作用域的语言来说,for语句初始化变量的表达式所定义的的变量,只会存在于循环的环境中。然而对于JavaScript来说,由for语句创建的变量i,即使在for语句循环结束后,也依旧存在于外部的执行环境中,这就是所说的变量提升。
es6新增了let和const命令,用来声明变量和常量,let命令只在所在的代码块内有效。
例子:

    {
        let a = 10;
        var b = 1;
    }
    console.log(a) //ReferenceError:a is not defined.
    console.log(b) //1

在上面的代码块之中,分别用let和var声明了两个变量。在代码块之外调用这两个变量,
发现let声明的变量错误,因为let的作用域是在它所在的当前代码块,不会被提升到当前函数的最顶部。

常见的面试题:

var a = [];
for (var i = 0;i < 10;i++){
    a[i] = function(){
        console.log(i);
    }
}
a[6](); //10

上面的代码中,变量i是var声明的,在全局范围内都是有效的,所以全局只有一个变量i,每一次循环,变量i的值都会发生变化,被赋给数组a的函数内部的console.log(i),里面的i指向的就是全局的i。也就是说,所有数组a的成员里面的i,指向的都是同一个i,导致运行时的输出的时最后一轮的i的值,也就是10.
如何使a[6]()输出的是6哪?

//es5闭包解决循环绑定问题
var a = [];
for (var i = 0;i < 10;i++){
    a[i] = (function(value){
        return function(){
            console.log(value)
        }
    })(i)
}
a[6](); //6

//es6
//使用let,声明的变量仅在块级作用域内有效
var a = [];
for (let i = 0;i < 10;i++){
    a[i] =  function(){
            console.log(i)
        }  
}
a[6](); //6
    上面代码中,变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。
因为JavaScript引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上运算。
    另外,for循环的一个特别的地方,就是设置循环变量的部分是一个父作用域,而循环体内部是一个单独的子作用域。
for(let i =0;i < 3;i++){
    let i = 'abc';
    console.log(i)
}
//abc
//abc
//abc
    上面代码输出3次abc。这说明函数内部的变量i与循环变量i不在同一个作用域内,有各自单独的作用域。

const声明一个只读的常量。一旦声明常量的值就不能改变.
const一旦声明变量,就必须立即初始化,不能留到以后赋值。

const PI = 3.1415;
PI; //3.1415
PI = 3; // TypeError: Assignment to constant variable
const foo;//SyntaxError: Missing initializer in const declaration

2、变量的解构赋值

什么是解构?

解构不是构造一个新的对象或者数组,而是逐个拆分现有的对象或数组、字符串,来提取需要的数据。
es6中被解构的数据项位于赋值运算符=的右侧,可以是数组、对象、字符串。

2.1、数组的解构

数组解构:使用一个数组作为一个数据项,根据数组模式(只要等号两边的模式相同,左边的变量就会赋予对应的值)从这个数组里面提取提取一个或者多个变量赋值。
基本用法:

//把数组中所有的数值赋给一个个单独的变量
let [a,b,c] = [1,2,3];
a  //1
b  //2
c  //3

//第一个不提取,其余都提取
let [,b,c] = ['li','yong','good'];
b  //'yong'
c  //'good'

//中间第二个不提取,其余都提取
let [a,,c] = ['li','yong','good'];
a  //'li'
c  //'good'

//最后一个不提取,其余都提取(不完全解构)
let [a,b] = ['li','yong','good']
a  //'li'
b  //'good'

//第一个提取,其余的放到一个数组里,要用到rest操作符
//rest操作符:用来获取多余的参数,将多余的参数放入数组中。
let [head,...tail] = [1,2,3,4];
head //1
tail //[2,3,4]

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

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

let [x,y = 'yong'] = ['li'];
x //'li'
y //'yong'

let [x,y = 'yong'] = ['li',undefined];
x //'li'
y //'yong'

let [x = 'li'] = [null]
x //null
如果一个数组成员是null,默认值不会生效。

以上代码中,undefined 和 null的区别:
undefined使用默认值;
null是有值,但值是空。

2.2、对象的解构

对象的解构与数组的解构不同,数组的元素是按次序排列的,变量的取值由它的位置决定;对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
基本用法:

//变量名和属性同名
let {a,b} = {a:'li',b:'yong'}
a //'li'
b //'yong'

//变量名与属性名不一致
let {a:xxx} = {a:'li',b:'yong'}
xxx //'li'
对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。

默认值:

let {x,y = 5} = {x:1};
x //1
y //5

let {x = 3} = {x: undefined};
x //3

let {x = 3} = {x:null};
x //null

如果将一个已经声明的变量用于解构赋值,必须小心
//错误的写法
let x;
{x} = {x:1};// SyntaxError: Unexpected token 
上面代码的写法会报错,因为JavaScript引擎会将{x}理解成一个代码块,从而发生语法错误。
//正确的写法
let x;
({x} = {x:1});
x //1

2.3 字符串的解构

字符串可以解构赋值。因为字符串被转换成一个类似数组的对象。

const [a,b] = 'yes';
a //'y'
b //'e'
c //'s'

2.4 函数参数的解构

function move({x = 0,y = 0} = {}){
    return [x, y];
}
move({x: 3, y:8}); // [3, 8]
move({x: 3});      // [3, 0]
move({})           // [0, 0]
move()             // [0, 0]
上面代码中,函数move的参数是一个对象,通过对这个对象进行解构,得到变量x 和 y 的值。如果解构失败, x 和 y 等于认值。
注意下面的写法:
function move({x, y} = {x: 0, y: 0}){
    return [x, y];
}
move({x: 3,y: 8}) //[3,8]
move({x:3})       //[3, undefined]
move({})          //[undefined,undefined]
move()            //[0, 0]
上面的代码是为函数move的参数指定默认值,而不是为变量x 和 y 指定默认值,所以得到与前一种写法不同的结果。

写了那么多,来总结一下在工作中的常用的例子:

  • 交换变量的值
    let x = 1;
    let y = 2;
    [x, y] = [y, x];
    x //2
    y //1
    上面的代码交换变量x 和 y 的值。
  • 从函数返回多个值
    函数返回多个值,只能将它们放在数组或对象里返回。
    有了解构赋值,取出这些值就非常方便了。
    
    //返回一个数组
    
    function example(){
        return [1,2,3];
    }
    let [a, b, c] = example();
    
    //返回一个对象
    function example(0{
        return {
            foo: 1,
            bar: 2
        }
    }
    let { foo, bar } = example();
  • 函数参数的定义
  解构赋值可以将一组参数与变量名对应起来
   //参数是一组有次序的值
    function f([x,y,z]){....}
    f([1,2,3])
    
   //参数是一组无次序的值
   function f({x, y, z}){...}
   f({z: 3, y: 2, x: 1}) 
  • 提取Json数据
    let jsonData = {
        id : 42,
        status: 'ok',
        data : [77,909]
    };
    let { id, status, data:number } = jsonData;
    id      // 42
    status  // 'ok'
    number  // [77,909]
  • 输入模块的指定方法
    加载模块时,指定输入哪些方法。
    const { SourceMapConsumer, SourceNode } = require("source-map");

3、模板字符串

es6引入模板字符串(``),进行字符串的拼接,对于字符串中嵌入变量,使用${}。

var str = '这是字符串变量';
$('#body').append(`liyong,${str},good`);
es5字符串查找:
    只有indexOf()方法,可以用来确定一个字符串是否包含里一个字符串。返回子字符串的位置(如果没有找到该子字符串,则返回-1)
    var d = 'this is a line';
    d.indexOf('is') //2
es6提供了一种查找子字符串的方法:includes()
    -includes(): 返回布尔值,表示是否找到了参数字符串。
    var d = 'this is a line';
    d.includes('is') //true

4、数组的知识

4.1数组的扩展运算符

    //将一个数组转化为用逗号分割的参数序列
    console.log([1,...[2,3,4],5]) //[1,2,3,4,5]

4.2、复制数组

数组是复合的数据类型,直接复制的话,只是复制的指向底层数据结构的指针,而不是克隆了一个新的数组。

    es5中数组的复制;
    const a1 = [1,2];
    const a2 = a1;
    a2[0] = 2;
    a1;  //[2,2]
    上面代码,a2不是a1的克隆,而是指向同一个数据的另一个指针。修改a2,会直接导致a1的变化。
    另外一种es5的方法:
    const a1 = [1,2];
    const a2 = a1.concat();
    a2[0] = 2;
    a1; //[1,2]
    上面代码中,a1会返回原数组的克隆,再修改a2就不会对a1产生影响。
    es6扩展运算符的复制数组的写法:
    const a1 = [1,2];
    const a2 = [...a1];
    a2[0] = 2;
    a1;  //[1,2]

4.3、合并数组

数组合并的写法:

    //es5
    const b1 = [3,4,5]
    [1,2].concat(b1) //[1,2,3,4,5]
    //es6
    [1,2, ...b1]     //[1,2,3,4,5]

4.4、Array.from()

将一组类似数组的对象(一组Dom节点)转为真正的数组

    let arrayLike = {
        '0':'li',
        '1':'yong',
        length:2
    }
    //es5的写法
    let arr = [].slice.call(arrayLike); //['li','yong']
    let arr = Array.prototype.slice.call(arrayLike);//['li','yong']
    //es6的写法
    let arr = Array.from(arrayLike); //['li','yong']

4.5、Array.of()

用于将一组值,转换为数组。

    Array.of(3,11,8)  //[3,11,8]

4.6、数组实例的find()和findIndex()

数组实例的find方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有的数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined.

    [1,4,-5,10].find((n) => n < 0)  //-5
    以上代码找出数组中第一个小于0的成员

4.7、数组实例的includes()

与字符串的includes方法类似,Array.prototype.includes方法返回一个布尔值。

    [1,2,3].includes(2);  //true
    [1,2,3].includes(4);  //false

4.8、数组实例的entries(),keys(),values()

keys()是对键名的遍历、values()是对键值的遍历、entries()是对键值对的遍历

 let arr = ['li','yong'];
 for(let [index,value] of arr.entries()){
    console.log(`索引 ${index} : 键值 ${value}`)
}
//索引 0 : 键值 li
//索引 1 : 键值 yong

4.9、数组的遍历方法

  • forEach:会自动省略为空的数组元素
  let arr = ['li','yong','good',''];
  arr.forEach((value,index)=>console.log(`索引${index} : 键值${value}`))
//索引0 : 键值li
// 索引1 : 键值yong
// 索引2 : 键值good
  • filter:创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有的元素。
    filter()不会对空数组进行检测
    filter()不会改变原始数组
   let arr = ['li','yong','good'];
   arr.filter(x=>{if(x == 'li'){return console.log(`筛选的是:${x}`)}}) 

4.10、数组转换字符串

  • join()方法
    let arr = ['li','yong','good'];
    console.log(arr.join('|'))
    //li|yong|good
  • toString()方法
    let arr = ['li','yong','good'];
    console.log(arr.toString())
    //li,yong,good

5、对象的扩展

5.1、对象的属性和方法的简写

    const name = 'li';
    const age = 00;
    const o = {name, age,method(){
        console.log(this.name)
    }}
    o.method() //'li'

5.2、Object.is()

es5 比较两个值是否相等,相等运算符(==)和严格相等运算符(===)。前者的不足是,会自动转换数据类型,后者的NaN不等于自身,以及+0等于-0。
es6 提出"Same-value-equality"(同值相等)。Object.is就是比较两个值是否严格相等。

    Object.is(true,1) //false
    Object.is(true,true) //true
    Object.is(+0,-0)   //false
    Object.is(NaN,NaN)  //true

5.3、Object.assign()

Object.assign方法用于对象的 合并,将源对象(source)的所有的可枚举属性,复制到目标对象(target)。

    const target = {a: 1};
    const source1 = {b: 2};
    const source2 = {c: 3};
    Object.assign(target, source1, source2)
    target //{a:1, b:2, c:3}

5.4、Object.assign()

  • 为对象添加属性
    const bbbb = {name:'li'};
    Object.assign(bbbb,{age:18,height:00})
    bbbb;
    //{
    // age:18
    // height:0
    // name:"li"
    // }
  • 为对象添加方法
    直接将两个函数放在大括号中,再使用assign方法添加到目标对象中。
    const bbbb = {name:'li'};
    Object.assign(bbbb,{

       getName(){
           return this.name;
       },
       getAge(){
           return this.age;
       }

    })

5.5、Object.keys(),Object.values(),Object.entries(),

返回一个数组
Object.entries的用途是遍历对象的属性。

    const obj = {name:'li',age:00 };
    for( let [key,value] of Object.entries(obj) ){
        console.log(`属性${JSON.stringify(key)}:属性值${value}`)
    }
    //属性"name":属性值li
    //属性"age":属性值00

你可能感兴趣的:(模块化,es6,webpack)