es6入门到五连绝世之双杀(double kill)

欢迎来到e6语法笔记教学

  1. ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的下一个版本标准,2015.06 发版。来学习的都应该对其有一定的了解了,在此不做过多陈述,这篇帖子主要是根据《 ES6从一脸懵逼到灵活运用》做的学习笔记。
  2. 这篇博客的记录手法,是通过 demo 记录 es6 要点,注释详细,运行结果也已备注,可能对于技术上的讨论很少,主要面向 es6 入门读者,篇幅可能很长,但是各个节点区分明确,可选择学习…

一、解构赋值篇

解构赋值允许你使用类似数组或对象字面量的语法将数组和对象的属性赋给各种变量。这种赋值语法极度简洁,同时还比传统的属性访问方法更为清晰。

1.1、对象解构

通过声明变量,提取定义对象中的属性值的方法。

<script type="text/javascript">
	//1、定义一个对象,下面的示例会有冲突,请分开截取运行
   const Tom = {
    
    
        name: 'Tom Jones',
        age: 25,
        family: {
    
    
            mother: 'Norah Jones',
            father: 'Richard Jones',
            brother: 'Howard Jones'
        },
   }

   //以前的属性提取方式
   //const name = Tom.name;
   //

   /*
      1、es6 对象提取
        --注意:{}中声明的变量要在作用域中没有定义过,变量名要和提取对象的属性名保持一致,才能完成映射
    */
   const {
    
    name , age } = Tom;
   console.log(`name=${
      
      name},age=${
      
      age}`); // name=Tom Jones,age=25


   // 2、对象结构也是可以嵌套的
   const {
    
    mother, father, brother} = Tom.family;
   console.log(`${
      
      mother},${
      
      father},${
      
      brother}`);   // Norah Jones,Richard Jones,Howard Jones


   //3、 提取变量重命名
   const father = 'Dad';    //变量已定义,下面的提取不报错就得给father重命名
   const {
    
    mother, father: f, brother} = Tom.family;
   console.log(f);  //Richard Jones,重命名定义的是 f 变量,对于重命名后的 father 属性是没有定义的,只能是重命名后的变量 f 访问



   // 4、如果获取对象中没有的属性,undefined
   const {
    
    mother, father, brother, sister} = Tom.family;
   console.log(sister);      //undefined

   // 5、给对象没有的属性一个默认的回滚值.还记得吗?只有变量为 undefined的才能赋默认值
   const {
    
    mother, father, brother, sister = 'have no sister'} = Tom.family;
   console.log(sister);     //have no sister
</script>

1.2、数组解构

<script type="text/javascript">

   // 1、定义一个对象,下面的示例会有冲突,请分开截取运行
   const numbers = ['one', 'two', 'three', 'four'];

   // 2、数组解构:从数组中提取值,按照对应位置(下标),对变量赋值
   const [one, two] = numbers;
   console.log(one, two); // one two

   // const [str1, str2] = numbers;
   // console.log(str1, str2); // one two

   // 3、中间有跳过解构的元素,需要使用空占位(因为是根据对应位置解构的)
   const [str1,  , str2] = numbers;
   console.log(str1, str2); // one three

   /*
     4、ES6引入了rest参数用于获取函数的多余参数,实际就是替换arguments对象
        提取第一个,剩下的形成新的数组(rest参数写法,rest参数只能放最后)
    */
   const [str01, ...others] = numbers;
   console.log(str01, others); // one ["two", "three", "four"]


   // 5、同理上一节对象解构,赋值默认值
   const details = ['JellyBool', 'laravist.com'];
   const [name, website, category = 'PHP'] = details;
   console.log(name, website, category);  // JellyBool laravist.com PHP


   // 6、实用场景,变量之间的值互换
   let a = 10;
   let b = 20;

   /*
       // 定义第三个变量中转交换
       let temp = a;
       a = b;
       b = temp;
       console.log(a ,b); //20 10
   */

    [b, a] = [a, b];
    console.log(a ,b); //20 10

</script>

1.3、字面量解构

<script type="text/javascript">

    /*
       1、 es6 对象字面量扩展
     */
    const name = 'Laravist';
    const age = 2;
    const birthday = '2015-09';

    // 对象属性赋值
    const laravist = {
    
    
        name: name,
        age: age,
        birthday: birthday,
        getName: function(){
    
    
            console.log(`${
      
      this.name }`);
        }
    }
    console.log(laravist);  //{name: "Laravist", age: 2, birthday: "2015-09", getName: ƒ}


    // 以上写法是很繁琐的,e6中当属性名与变量名一致的时候,写一次即可完成赋值,因为指向一致
    const Laravist = {
    
    
        name,               // 属性简写
        age,
        birthday,
        getName(){
    
             // 方法简写
            console.log(`${
      
      this.name }`);
        }
    }
    console.log(Laravist);  // {name: "Laravist", age: 2, birthday: "2015-09", getName: ƒ}
    Laravist.getName();     // Laravist


    // 2、计算属性,定义属性名时可动态生成
    let id = 0;
    const userIds = {
    
    
        [`user-${
      
      ++id }`]: id,
        [`user-${
      
      ++id }`]: id,
        [`user-${
      
      ++id }`]: id
    }
    console.log(userIds);   // {user-1: 1, user-2: 2, user-3: 3}


    // 3、计算属性更灵活的使用
    const keys = ['name', 'age', 'birthday'];
    const values = ['Jerry', '5', '2018-08'];
    const Jerry = {
    
    
        // shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值
        [keys.shift()]: values.shift(),
        [keys.shift()]: values.shift(),
        [keys.shift()]: values.shift(),
    }
    console.log(Jerry);     //{name: "Jerry", age: "5", birthday: "2018-08"}

</script>

二、循环遍历

2.1、for ,of 遍历简介

<script type="text/javascript">

   // 定义一个数组,循环遍历
   const fruits = ['Apple', 'Banana', 'Orange', 'Mango'];
   // 为其原型对象加个值
   fruits.describe = "My favorite fruits";


   // 1、此循环比较繁琐,可读性也不是很高
   for(let i=0; i<fruits.length; i++){
    
    
         console.log(fruits[i]);    //逐个打印
   }


   // 2、js 提供的数组遍历函数,简化了语法,使用 fruit 变量参数遍历即可
   fruits.forEach( fruit => {
    
    

        // 缺点: 不能终止或跳过,下面的break,continue 会报错
        if(fruit === 'Orange'){
    
    
            //break;    //SyntaxError: Illegal break statement
            //continue;   //SyntaxError: Illegal continue statement: no surrounding iteration statement
        }
        console.log(fruit);        //逐个打印
   });


   // 3、for in 循环遍历下标
   for(let index in fruits){
    
    
        console.log(fruits[index]);    //缺点:逐个打印,还会打印其原型对象添加的值My favorite fruits
   }



   // 4、推荐使用 for of,取上之精华,去之其糟粕
   for(let fruit of fruits){
    
    

        //  支持终止与跳过
       if(fruit === 'Orange'){
    
    
            break;
            //continue;
        }
        console.log(fruit);        //逐个打印
   }
</script>

补充:有些场景可能需要使用到 index 下标
es6-for…of 循环一个数组返回索引的语法:
for(let [index,elem] of new Map( arr.map( ( item, i ) => [ i, item ] ) )){
  console.log(index);
  console.log(elem);
}

<script type="text/javascript">

	var arr = [ 'a', 'b', 'c' ];
	// new Map() 将其每次循环返回的 key=value,构建成新的 map
	for( let [i, item] of new Map( arr.map((item, i) => [i, item]) ) ){
    
    
		console.log( i, item ); //0 "a"     1 "b"       2 "c"
	}

</script>

2.2、for ,of 遍历示例

上一节讲到 for … of 可遍历可迭代对象,可迭代对象是部署了Iterator接口,或者定义了 [ Symbol.Iterator ] 方法的数据结构,遍历器便提供了这样的一种遍历方式。

<script type="text/javascript">

   // 1、定义一个数组,使用遍历器循环遍历
   const fruits = ['Apple', 'Banana', 'Orange', 'Mango'];

   // 接受其遍历器对象
   const iterator = fruits.entries();
   for(let fruit of iterator){
    
    
        // 其遍历器返回的是有下标的数组,这样既可以得到值,又能获得下标
        console.log(fruit);     //[0, "Apple"], [1, "Banana"], [2, "Orange"], [3, "Mango"]
        console.log(fruit[1]);  // 每次循环获得上面数组的第二的元素,Apple  Banana  Orange  Mango
   }

   // 解构语法改写
   for(let [index, fruit] of fruits.entries()){
    
    
        // 理想状态的遍历结果如下
        console.log(`${
      
      fruit} ranks ${
      
      index + 1} in my favorite fruits`);
   }



   // 2、 遍历参数 arguments 对象
   function sum(){
    
    
        let total = 0;
        // 这里是一个参数对象arguments,虽然不是数组,但可以使用 for...of 遍历
        for(let num of arguments){
    
    
            total = num + total;
        }
        console.log(total);     // 612
        return total;
   }
   sum(10,24,58,69,451);


   // 3、遍历字符串
   let name = 'Tom';
   for(let char of name){
    
    
        console.log(char);  //逐个打印 T  o  m
   }


   // 4、遍历 nodlist 类型的标签集合
   // 获取网页中所有 <li> 标签
   const list = document.querySelectorAll('li');
   for(let li of list){
    
    

        // meige li 都绑定一个点击事件
        li.addEventListener('click', function(){
    
    
            // 被点击的对象添加高亮样式
            this.classList.toggle('highlight');
        });
   }
   
</script>

三、Array数组方法

3.1、Array.from() … of() 浅析

e6 为类数组提供的新方法 Array.from() ,Array.from() 方法从一个类似数组或可迭代对象中创建一个新的。类数组对象就是拥有 length 属性,可遍历的对象。

<ul>
   <li>Go to store</li>
    <li>Watch TV</li>
    <li>Go Shopping</li>
</ul>
<script type="text/javascript">

		// 1、 将标签元素集合对象转换为数组
       const todos = document.querySelectorAll('li');
       console.log(todos);  // f12 看其打印类型,_proto__: NodeList

       // 必须要将todos转换为 数组对象,才能调用数组原型的 map() 方法
       const todosArr = Array.from(todos);
       const names = todosArr.map(todo => todo.textContent);
       console.log(names);      // ["Go to store", "Watch TV", "Go Shopping"]


       // Array.from()的第二个参数(可选),mapFn 最后生成的数组上再执行一次 map 方法后再返回
       // 将上面内容可改写成一步
       const strs = Array.from(todos, todo => todo.textContent);
       console.log(strs);      // ["Go to store", "Watch TV", "Go Shopping"]


        // 2、将 arguments 参数转换为数组
       function sum(){
     
     
         console.log(arguments);    // f12 查看其类型__proto__: Object
         // reduce()调用之前,必须将 arguments 转为数组
         return Array.from(arguments).reduce((prev, curr) => prev + curr, 0);
       }
       console.log(sum(78,85,63));  //226


       // 3、字符串转换为数组
       const website = "Laravist";
       console.log(Array.from(website));    //["L", "a", "r", "a", "v", "i", "s", "t"]
       
</script>

Array数组创建时,由于传入参数个数不一样,导致其方法的创建行为是不一样的,Array.of()能解决这样的不一致性,Array.of() 方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。
看下图:
在这里插入图片描述

<script type="text/javascript">
	 let news = new Array(7);
     console.log(news);   //(7) [empty × 7],长度为7,各元素为空的数组

     let arr = Array.of(7);
     console.log(arr);        //[7],长度为1,元素是7
     arr = Array.of(7, 2, 3);
     console.log(arr);        //[7, 2, 3]

</script>

3.2、Array 其他实用方法

 <script type="text/javascript">

    // 1、 声明了一个数组对象
    const inventory = [
        {
    
    name: 'apples', quantity: 2},
        {
    
    name: 'bananas', quantity: 0},
        {
    
    name: 'cherries', quantity: 5}
   ];


   /*
     1、 查找数组中满足某个条件的元素,相对于for...of 循环,使用方法更简便
        find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined,找到立马return
        参考:https://www.runoob.com/jsref/jsref-find.html
   */
   const bananas = inventory.find( (currentValue, index, arr) => {
    
    
        if(currentValue.name === 'bananas'){
    
    
            return true; // 找到 return true, bananas变量接受到当前浏览的对象
        }
         return false;
    });

   //const bananas1 = inventory.find( fruit => fruit.name === 'bananas'); //简写形式,推荐
   console.log(bananas);    //{name: "bananas", quantity: 0}


   /*
     2、 同理,查询数组中某个条件的元素的下标,找到立马return
        findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。
    */
   const cherries = inventory.findIndex(fruit => fruit.name === 'cherries'); //简写
   console.log(cherries);      //2 ,这是返回的下标



   /*
     3、 检测数组中是否存在至少一个元素,满足自己传入的函数检验,存在-->true, 不存在 --> false (至少一个返回true)
        some() 方法检测 TypedArray 的一些元素是否通过所提供函数的测试。
    */
   const isEnough = inventory.some(fruit => fruit.quantity >0 );
   console.log(isEnough);   // true


   /*
     4、 同上,检测所有元素是否满足传入函数,一个不满足马上返回 false
        every() 方法测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。
    */
   const isAllEnough = inventory.every(fruit => fruit.quantity >0 );
   console.log(isAllEnough);   // false

</script>

四、剩余参数与扩展运算符

4.1、剩余参数使用

JS函数内部有个arguments对象,可以拿到全部实参。现在ES6给我们带来了一个新的对象,可以拿到除开始参数外的参数,即剩余参数。

理解:剩余参数语法允许我们将一个不定数量的参数表示为一个数组

<script type="text/javascript">

    /*
        1、 剩余参数,用于对参数需要计算的场景
           ...numbers : ...后加上自定义的参数变量名 numbers 即可
     */
    function sum(...numbers){
    
    

        console.log(numbers);   //(4) [1, 2, 5, 4], __proto__: Array(0),原型为数组,与 arguments 区别
        return numbers.reduce((prev, curr) => prev + curr, 0);
    }
    console.log(sum(1, 2, 5, 4));    // 12



    /*
        2、 剩余参数只能是函数形参的最后一个的位置,且前面可以有多个其他形参
     */
    function converCurrency(rate, ...amounts){
    
    

        console.log(rate, amounts);   // (3) [2, 5, 4], 只接受剩下没有映射的的参数,与 arguments 区别
        return amounts.map(amount => amount * rate);
    }
    console.log(converCurrency(0.85, 2, 5, 4)); //(3) [1.7, 4.25, 3.4]


    /*
        3、 应用于数组的解构
     */
    const player = ['Jelly', 12345, 6, 8, 5, 7];
    const [name, id, scores] = player;  // 复习,数组结构是下标对应映射
    console.log(name, id, scores);     //Jelly 12345 6 , 解构时 player 后面下标位没有则没有映射传入

    // 如果 scores1 解构剩余的元素,使用剩余参数
    const [name1, id1, ...scores1] = player;  // 复习,数组结构是下标对应映射
    console.log(name1, id1, scores1);       //Jelly 12345 (4) [6, 8, 5, 7]


</script>

4.2、扩展运算符

扩展运算符是把一个可遍历的对象的每个元素,扩展成一个新的参数序列

<script type="text/javascript">

    /*
        数组之间的整合,由浅入深,讲解
     */
    const youngers = ['George', 'John', 'Tom'];
    const olders = ['Tencent', 'Baidu', 'Ali'];

    // 1、利用数组的 concat() 方法,将数组整合为一个新的数组,原数组不变
    const numbers = youngers.concat(olders);
    console.log(youngers);  // ["George", "John", "Tom"]
    console.log(numbers);   // ["George", "John", "Tom", "Tencent", "Baidu", "Ali"]


    // 2、如果想在整合时在 youngers 和 olders 中新加一个 marry,老套用法
    let nums = [];         //先定义这是个数组
    nums = nums.concat(youngers);
    nums.push("Marry");     // 从数组尾部追加一个元素
    nums = nums.concat(olders);
    console.log(nums);     // ["George", "John", "Tom", "Marry", "Tencent", "Baidu", "Ali"]


    // 3、扩展运算符
    const str = 'Jerry';
    const sarr = [...str];  // 将每个字符扩展成了数组元素。此处等同 [...'Jerry']
    console.log(sarr);      //  ["J", "e", "r", "r", "y"]


    // 4、利用扩展运算符整合 youngers 和 olders
    let news = [...youngers, ...olders];
    console.log(news);      // ["George", "John", "Tom", "Tencent", "Baidu", "Ali"]


    // 5、当然,新增 marry 如下:
    const newS = [...youngers, 'Marry', ...olders];
    console.log(newS);      // ["George", "John", "Tom", "Marry", "Tencent", "Baidu", "Ali"]




    // 6、浅析关于数组间赋值,是对象间的地址的引用
    let s1 = youngers;
    s1[0] = 'Str';          // 改变了 s1 数组的0下标元素值,打印发现 youngers 数组也发生了变化
    console.log(s1);        //  ["Str", "John", "Tom"]
    console.log(youngers);  //  ["Str", "John", "Tom"]


    // 6.1、杜绝上面的现象,利用 concat() 生成一个新的数组
    let s2 = [].concat(olders);
    s2[0] = 'Change';
    console.log(s2);        // ["Change", "Baidu", "Ali"]
    console.log(olders);    // ["Tencent", "Baidu", "Ali"]


    //6.2、使用扩展运算符改写
    let s3 = [...olders];
    s3[0] = 'Hello';
    console.log(s3);        // ["Hello", "Baidu", "Ali"]
    console.log(olders);    // ["Tencent", "Baidu", "Ali"]

</script>

4.3、扩展运行符示例

1、 下面这个是一个结合扩展运算符,写的一个漂亮的 css 动态展示效果,里面介绍了两个有意思的 css 属性:transform、transition。

<style>
    .highlight{
    
    
        padding: 2px 5px;
        background: #00adb4;
        color: white;
    }

    .heading{
    
    
        justify-content: center;
        align-items: center;
        font-family: sans-serif;
        font-size: 50px;
        color: white;
        text-shadow: 3px 3px 0 rgba(0, 0, 0, 0.2);
        background-color: #f2be45;
        display: inline-block;
    }

    .heading span{
    
    
        cursor: pointer;
        display: inline-block;
        /*
            transition 属性是一个简写属性,用于设置四个过渡属性
            参考:https://www.w3school.com.cn/cssref/pr_transition.asp
         */
        transition: transform 0.25s;
    }

    .heading span:hover{
    
    
        color: black;
        /*
            transform 属性向元素应用 2D 或 3D 转换。该属性允许我们对元素进行旋转、缩放、移动或倾斜
            参考地址:https://www.w3school.com.cn/cssref/pr_transform.asp

            注意:对于内联元素 span 是不会有旋转效果的,所以上面的样式将 span 设置了 display: inline-block;
         */
        transform: translateY(-20px) rotate(10deg) scale(2);
    }
</style>
<body>

<h2 class="heading">LARAVIST!</h2>
<script type="text/javascript">

    /*
       通过 js 为上方h2标签元素的内容添加样式
     */
    const heading = document.querySelector(".heading");

    // 定义函数,将字符串内容扩张成字符数组,逐一处理
    function wrapWithSpan(context){
     
     
        //下面这一步简写,是不是很简单,此处所涉及到的都是之前举例过的知识
        return [...context].map(text => `<span>${
       
       text}</span>`).join('');
    }

    console.log(wrapWithSpan(heading.textContent));     // 查看返回的数据

    // 将返回的数据重新写回 h2 标签元素
    heading.innerHTML = wrapWithSpan(heading.textContent);

</script>
</body>

在这里插入图片描述

2、 扩展运算符应用于标签元素,对象属性,数组元素的示例。

<ul>
   <li>Go to store</li>
    <li>Watch TV</li>
    <li>Go Shopping</li>
</ul>
<script type="text/javascript">

    /*
       1、 应用于标签元素
     */
    const todos1 = document.querySelectorAll("li");     //__proto__: NodeList
    console.log(Array.from(todos1));     // 使用之前讲解的方法将其转换为 数组类型

    // 使用扩展运算符将todos转为数组再调用map()方法
    console.log([...todos1].map(todo => todo.textContent));  // ["Go to store", "Watch TV", "Go Shopping"]



   /*
        2、 扩展对象的属性
     */
    const favorites = {
     
     
        color: ['white', 'black'],
        fruit: ['banana', 'mongo']
    }
    // 在购买的列表中把喜欢的对象的水果属性扩展进来
    const shoppingList = ['milk', 'sweets', ...favorites.fruit];
    console.log(shoppingList);     // ["milk", "sweets", "banana", "mongo"]


    /*
        3、 扩展数组元素, 删除 todoss 数组中id为1(下标为1)的元素
     */
    let todos = [
        {
     
     id: 1, name: 'go to store', complete: false},
        {
     
     id: 2, name: 'watch TV', complete: true},
        {
     
     id: 3, name: 'go shopping', complete: false}
    ]

    const todoIndex = todos.findIndex(todo => todo.id === 2);  // 获得下标 1
    /*
        arrayObject.slice(start,end):可从已有的数组中返回选定的元素。
            --start   必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。
            --end   可选。规定从何处结束选取。如果没有指定该参数,那么切分的数组结束的所有元素。

        参考地址:https://www.w3school.com.cn/jsref/jsref_slice_array.asp
     */
    //  下面注释内容得到的是一个二维数组,因为 slice() 切分得到是数组,而不是对象
    // const newTodos = [todos.slice(0, todoIndex), todos.slice(todoIndex + 1)];    // [Array(1), Array(1)]

    const newTodos = [...todos.slice(0, todoIndex), ...todos.slice(todoIndex + 1)]; //通过扩展运算符,迭代数组中的元素(对象),得到对象
    console.log(newTodos);  // [{…}, {…}]

    todos = newTodos;
    console.log(todos); // [{…}, {…}]

</script>

3、 扩展运算符应用到函数参数的传入。

<script type="text/javascript">

    /*
       1、 扩展运算符在函数中运用,数组追加元素
     */
    const fruit = ['apple', 'banana', 'pear'];
    const newFruit = ['orange', 'mongo'];

    // 将 newFruit 添加到 fruit 中
    //  fruit.push(newFruit);  // ["apple", "banana", "pear", Array(2)] ,添加的元素为数组,不是我们想要的

    /*
        apply:方法能劫持另外一个对象的方法,继承另外一个对象的属性
            Function.apply(obj,args)方法能接收两个参数
                obj:这个对象将代替Function类里this对象
                args:这个是数组,它将作为参数传给Function(args-->arguments)
     */
    // fruit.push.apply(fruit, newFruit); //["apple", "banana", "pear", "orange", "mongo"] ,可以利用 apply() 传值

    fruit.push(...newFruit);   // es6 写法,简单快捷,需注意这不同于 concat(),这里更改的就是原来的数组
    console.log(fruit);         //  ["apple", "banana", "pear", "orange", "mongo"],



    /*
        2、 日期函数传参
     */

    const dateFields = [2019, 9, 12];
    // const date = new Date(dateFields[0], dateFields[1], dateFields[2]); //想利用这种数组来构建是不是很繁琐

    const date = new Date(...dateFields);   // es6改写,再多参数也灵活传入
    console.log(date);  // Sat Oct 12 2019 00:00:00 GMT+0800 (中国标准时间)

</script>

猜你喜欢

转载自blog.csdn.net/w2462140956/article/details/100117084