【前端】ES6

本文介绍了ES6中的let和const关键字,它们提供了块级作用域,防止变量污染全局。let不允许重复声明,const用于定义常量。还讲解了箭头函数的使用,它的this指向定义时的作用域。此外,讨论了Promise对象在异步编程中的应用,以及Generator和async函数如何处理复杂的异步流程。
摘要由CSDN通过智能技术生成

let 和 const

类似var定义变量,但是let修饰的变量仅在声明的代码块中有效;
var声明的变量,在全局有效

for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}

js中的for循环声明循环变量的部分也作为一个父作用域,即(let i = 0; 😉, 而代码块部分的let i = ‘abc’为一个子作用域。
let修饰的变量必须先声明再使用。

let 和 var 使用对比:

<ul>
   <li>1</li>
   <li>2</li>
   <li>3</li>
   <li>4</li>
 </ul>
 <script>
   const lis = document.querySelector('ul').querySelectorAll('li')
   for (var i = 0; i < lis.length; i++) {
     lis[i].addEventListener('click', function () {
       console.log(lis[i]);  // undefined
     })
   }
 </script>

这里使用var作为循环变量的声明,但由于使用的是var,所以 i 为全局变量,当循环结束 i 数值为 lis.length, 超过数组下标;当触发事件的时候 lis[i] 下标越界因此为 undefined;
解决方案为使用 let 替代 var,这样含义为在每一次绑定事件时声明一个 let i 记录当前下标。

只要使用let 进行声明变量后,那么该变量之前的部分称为 “死区”,再死区部分使用let变量会报错

temp = "abc"

let temp;  // 该代码之前为死区部分,无法访问

let修饰的变量,不允许重复声明。

ES6中的块级作用域中允许声明函数。

const修饰的变量表示常量,一旦声明,不能改变。维护的是变量指向的内存地址是不变的。

字符串

字符串多行定义

ES6中可以使用反引号(`)标识,当作普通的字符串或者定义多行字符串,或者嵌入变量
在这里插入图片描述

new Vue({
   el: '#app',
    computed: {
        b() {
            let [name, age] = ['righteye', 18]
            return `this is a template string, username = ${name}, age = ${age}`
        }
    }
})
标签模板

一种函数调用的特殊形式,以 tag`content` 的形式进行展现,其中tag为函数名,后面的content为反引号包裹的模板字符串。
参数:param会接收被${} 变量分割的普通的字符串信息,变量会被后面的其他参数接收。

new Vue({
    el: '#app',
    methods: {
        f(param, ...val) {
            // param: ['hello', 'world']
            // val: ['righteye', 18]
            // typeof val: object
            console.log(param, val, typeof val)  
            return param + val
        }
    },
    computed: {
        a() {
            let name = 'righteye'
            let age = 18
            return this.f`hello ${name} world ${age}`
        },
        b() {
            let [name, age] = ['righteye', 18]
            return `this is a template string, username = ${name}, age = ${age}`
        }
    }
})

箭头函数

ES6可以使用箭头函数简化代码的书写:

var f = v => v;

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

对于普通函数,内部的this指向运行时的所在的对象,即调用者;而对于箭头函数,this指向定义时所在的作用域, 函数的所用者

<p id="banner"></p>
<p id="demo"></p>

<p id="res"></p>

<script>
    function Hello() {
        this.s1 = 2;
        this.s2 = 0;
        // setTimeout(function() {
        //     console.log(this); // Window
        //     document.getElementById("banner").innerText = "我是普通函数"
        //     document.getElementById("demo").innerText = ++this.s1 + " " + this.s2;  // NaN undefine
        // }, 1000);
        setTimeout(() => {
            console.log(this);  // Hello
            document.getElementById("banner").innerText = "我是箭头函数"
            document.getElementById("demo").innerText = ++this.s1 + " " + this.s2;  // 3 0
        }, 1000);
    }

    h = new Hello();

    document.getElementById("res").innerText = h.s1 + " " + h.s2;
</script>

上述案列中在传统 function() 定义方式中, 定时器执行指向调用者为 window 对象; 而使用箭头函数执行时 this 执行为声明时作用域, 即 funciton Hello() {}, 因此返回 Hello。

另外的, 箭头函数中不存在 arguments 参数,不能作为构造函数声明对象。对于 arguments 参数, es6 中使用 rest 参数进行替代

let fn = (...args) => {
	console.log(args);  // (5) [1, 2, 3, 4, 5]
}
fn(1, 2, 3, 4, 5);  

使用 ‘…参数名称’ 并放在所有形参的末尾,参数类型为数组。

// ES6
function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

// ES5
function foo() {
  var _this = this;

  setTimeout(function () {
    console.log('id:', _this.id);
  }, 100);
}

迭代器的使用

使用迭代器的对象,内部包含 Symbol.iterator 属性,此类对象可以使用 for … of 进行遍历,相对 for … in 获得 key ,该遍历用于获取 value。

const arr = {
  name: 'abc',
  status: [
    'lufei',
    'suolong',
    'shanzhi',
    'qiaoba'
  ],
  // 1. 迭代对象需要包含 Symbol.iterator 属性
  // 2. Symbol.iterator 返回一个对象
  // 3. [2]中返回对象需要包含 next 方法
  // 4. 返回的对象需要包含 value 和 done 属性
  [Symbol.iterator]() {
    let index = 0;
    return {
      next: () => {
        if (index < this.status.length) {
          return {
            value: this.status[index++],
            done: false
          }
        } else {
          return { value: undefined, done: true }
        }
      }
    };
  }
}
// 遍历 arr, 直接返回 status 中的值
for (let value of arr) {
  console.log(value);
}

Promise

  1. 异步编程的一种解决方案;通过new Promise()可以创建对象,该对象具有状态:进行中,已成功,已失败,一旦使用resolve()状态便定性不可以再更改,后续的回调方法也会理解得到当前状态下的结果。
    通过Promise可以将异步的操作同步的表现出来。

  2. Promise中的then()添加再Promise.prototype的原型链上,可以为Promise实例添加状态改变时的回调函数;也就是可以通过返回Promise对象继续再then()的方法中改变当前Promise的状态(resolve/reject),以链的形式调用then()方法

  3. Promise.prototype.catch可以捕获reject抛出的异常;但是在调用resolve()后再次抛出异常是无效的。

const promise = new Promise(function(resolve, reject) {
  resolve('ok');
  throw new Error('test');  // 无效的抛出异常
});
  1. Promise的错误具有冒泡的性值,可以一直上传直到被捕获。
<div id="app">
        <span> {{ value }} </span>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <script>
        new Vue({
            el: '#app',
            data: {
                value: ''
            },
            methods: {
                onPromiseHandle(data) {
                    return new Promise((resolve, reject) => {
                        resolve(data);   // resolve的调用会继续进入then语句中
                        // reject("fail"); // reject会被catch捕获,如果没有继续向上抛出异常
                    }).then((data) => {
                        return Promise.resolve(data + 'js');
                    }).then((data) => {
                        return Promise.resolve(data + "xxx");
                    }).then((data) => {
                        this.value = data;
                        return this.value;
                    })
                    // .catch((err) => {
                    //     console.log(err)
                    // })
                }
            },
            mounted() {
               this.onPromiseHandle("hello").then((data) => {
                    console.log("=>", data)
               }).catch((err) => {
                    console.log("error=>", err)
               })
            }
        })
    </script>

其中 Promise.resolve()等价于:

Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))

Generator

function* helloWorldGenerator() {
  yield 'hello';
  yield 'world';
  return 'ending';
}

var hw = helloWorldGenerator();

通过yield定义不同的状态,使用* 号定义Generator返回迭代器对象;每一次需要以hw.next()的方式进行获取yield的结果

hw.next()
// { value: 'hello', done: false }

hw.next()
// { value: 'world', done: false }

hw.next()
// { value: 'ending', done: true }

hw.next()
// { value: undefined, done: true }

yield类似暂停的函数,遇到yield后会将yield后的表达式结果作为返回值,并且阻塞后面的操作,只有在调用next()后才会继续执行。
一个函数中可以执行多个yield,但是只能有一个return

async函数

相比于Generator,async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await

new Vue({
    el: '#app',
    data: {
    },
    methods: {
        *testGenerator() {  // 定义一个Generator
            for (let i = 0; i < 5; i++) {
                yield i + 1
            }
        }
    },
    computed: {
        a() {
            let res = ""
            let taskObj = this.testGenerator();
            let task;
            while (!(task = taskObj.next()).done) {  // 消费task的value
                res += task.value;
            }

            return res
        }
    }
})
const asyncReadFile = async function () {
  const f1 = await readFile('/etc/fstab');
  const f2 = await readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};

类似的ES6 还有 class 扩展, 类比 Java, 包含 set 和 get 方法, 类继承等

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值