尚硅谷 ES6-12 笔记

本文详细介绍了从ES6到ES12的各个版本中的新特性,包括let和const关键字、模板字符串、箭头函数、Promise、Set和Map、类、数值和字符串扩展、模块化等内容。讲解了新特性如何使用以及它们在实际开发中的应用,帮助开发者更好地理解和掌握JavaScript的最新进展。
摘要由CSDN通过智能技术生成

ES介绍

ES就是ECMAScript简称,JS就是ES的一个实现,这里ECMA(欧洲计算机制造商学会)每年发布一个ES新版本,2020年到了ES11,前置内容: JS,Ajax,Promise

为什么从ES6开始: 变动多,有里程碑意义,新增语法特性

ES兼容性查询网站,即使不兼容我们也可以通过编译器编译成ES5

ES6新特性

eval函数(ES3函数补充)

eval()函数可计算某个字符串,并执行其中的的JavaScript代码。

  • 语法: eval(string)
    string: 要计算的字符串,其中含有要计算的 JavaScript 表达式或要执行的语句。
  • 返回值
    通过计算 string 得到的值(如果有的话)。
  • 说明
    该方法只接受原始字符串作为参数,如果 string 参数不是原始字符串,那么该方法将不作任何改变地返回。因此请不要为 eval() 函数传递 String 对象来作为参数。
  • 如果试图覆盖 eval 属性或把 eval() 方法赋予另一个属性,并通过该属性调用它,则 ECMAScript 实现允许抛出一个 EvalError 异常。
  • 抛出
    如果参数中没有合法的表达式和语句,则抛出 SyntaxError 异常。如果非法调用 eval(),则抛出 EvalError 异常。如果传递给 eval() 的 Javascript 代码生成了一个异常,eval() 将把该异常传递给调用者。
  • 虽然 eval() 的功能非常强大,但在实际使用中用到它的情况并不多。不同浏览器不同版本对eval处理有差异

实例

eval("x=10;y=20;document.write(x*y)")
console.log(eval("2+2"))
var x=10
console.log(eval(x+17))

输出

200
4
27
  • 作用域
    var x = 1;
    (function () {
         
        eval('var x = 123;');
        console.log("I",x)
    })();
    console.log(x);
    
    var x = 1;
    (function () {
         
        window.eval('var x = 123;');
        console.log("I",x)
    })();
    console.log(x);
    
    在ES<=8,得到的是
    I 123
    1
    I 123
    1
    
    在ES>8得到的是
    I 123
    1
    I 123
    123
    
    在ES8-下eval是函数作用域,在ES8+下eval的作用域取决于调用者

let关键字

  • var的级别用法一样
  • let不可以重复声明,但是var可以
    var varIns = "A";
    var varIns = "B"; // 合法
    let letIns = "A";
    let letIns = "B"; // 不合法
    
  • let具有块级作用域,var没有块作用域,JS的作用域有
    • 全局作用域(例如a=1,那么a就是window的成员)
    • 函数作用域(例如在函数中var a=1, 那么出了函数a就没了)
    • eval作用域
    • 块作用域(例如{a=1},if(){},while(){}…,那么在括号外面a就不可用)
  • let不存在变量提升,例如
    console.log(a);       // 输出undefined
    var a=1;
    console.log(a);       // 输出1
    
    console.log(b);       // 报错
    let b=1;
    console.log(b);
    
  • let不影响作用域链
    虽然是块级作用域,但是不影响如果函数内部没有变量会自动往外找

实例

在以前写代码的时候我们遇到过这个问题

// 我有5个button
var btns = document.querySelectorAll("button");
for(var i = 0;i < btns.length;i++){
   
    btns[i].onclick = function(){
   
        console.log(i);
    }
}

这时候不管点哪个都显示5,这是因为onclick里面没有i,于是闭包传输了i,这个i是外面的i,i在变化,到点击的时候相当于是走完了

{
   var i=0} //第1个循环
{
   var i=1} //第2个循环
{
   var i=2} //第3个循环
{
   var i=3} //第4个循环
{
   var i=4} //第5个循环

这个时候i就是5,因为i是for的块级作用域内部变量,var没有块级作用域,第二个循环的修改会影响第一个循环的i

我们有两个修改方法

增加参数

var btns = document.querySelectorAll("button");
for(var i = 0;i < btns.length;i++){
   
    btns[i].idx = i;
    btns[i].onclick = function(){
   
        console.log(this.idx);
    }
}

修改为let

// 我有5个button
var btns = document.querySelectorAll("button");
for(let i = 0;i < btns.length;i++){
   
    btns[i].onclick = function(){
   
        console.log(i);
    }
}

相当于执行了

{let i=0} //第1个循环
{let i=1} //第2个循环
{let i=2} //第3个循环
{let i=3} //第4个循环
{let i=4} //第5个循环

let有块级作用域,第二个循环的修改不会影响第一个循环的i=1

const关键字

  • 格式于let一样
  • 必须赋初值
  • 建议大写
  • 不能修改
  • 有块级作用域
  • 常量指向数组/对象的修改不算修改,因为const对象指向的地址没有变

变量解构赋值

可以按照一定模式从数组/对象提取值,对变量进行赋值

  • 对数组进行解构[...]=Array,就是找对应元素分别对应数组,例如

    let [a,b,c,d]=[111,222,333,"789"];
    console.log(a);
    console.log(b);
    console.log(c);
    console.log(d);
    

    不是很常用

  • 可以对对象进行解构{...}=Object,要求变量名一一对应,例如

    let t={
         
        a:111,
        b:222,
        d:333,
        c:function(){
         console.log("OK")}
    }
    let {
         a,b,c,d}=t;
    console.log(a);
    console.log(b);
    console.log(c);
    c();
    console.log(d);
    d();              // Error
    

    解构一般用于提取方法,例如我之前要写t.c()就可以简写成c()

  • 解构时候如果数目不同/不匹配时,会尽量匹配,例如

    let [a,b] = [1,2,3]  // a=1 b=2
    let [a,b,c,d] = [1,2,3]  // a=1 b=2 c=3 d=undefined
    let t={
         
        x:111,
        y:222,
        z:333,
        w:function(){
         console.log("OK")}
    }
    let {
         x,y} = t;      // x=111 y=222
    let {
         z,w,s} = t;    // z=333 w=[function] s=undefined
    
  • 解构支持默认值
    JS确认某个参数要使用默认值是这个参数===undefined

    let [m1,m2="S"] = ["A"]   // m1="A" m2="S"
    let [n1,n2="S"] = ["A",undefined]   // n1="A" n2="S"
    let [p1,p2="S"] = ["A",null]   // p1="A" p2=null
    
  • 字符串的解构赋值
    将字符串转化为数组

    let [a,b,c] = "Liu" // a="L" b="i" c="u"
    
  • 数值与布尔值解构

    let {
         toString: s}=123;
    console.log(s===Number.prototype.toString)
    let {
         toString: r}=true;
    console.log(r===Boolean.prototype.toString)
    

    都是true

  • 函数参数解构

    function foo([a,b]){
         
      console.log(a,b); // 1,2
    }
    foo([1,2])
    
    function foo2({
          a=0,b=0}={
          }){
                 // 无参时默认{} a,b也有默认值
    //function foo2({a,b}={a=0,b=0}){   // 注意,这两种方法出的结果不同    
      console.log(a,b);
    }
    foo2({
         a:1,b:2})         // 1,2
    foo2({
         a:1})             // 1,0
    foo2({
         a:undefined,b:2}) // 0,2
    foo2()                  // 0,0
    
  • 用处

    • 交换值[a,b]=[b,a]
    • 接受函数返回对象/数组
    • 函数参数定义
    • 函数参数默认值
    • 加载模块
      const {
              SourceMapConsumer, SourceNode} = require("source-map")
      
    • 获取map值
      let map = new Map();
      map.set("a","A")
      map.set("b","B")
      
      // 获取键值
      for (let [key,value] of map) {
             
        // ...
      }   
      
      // 获取键名
      for (let [key] of map) {
             
        // ...
      }   
      
      // 获取键值
      for (let [value] of map) {
             
        // ...
      }
      
  • 补充for的遍历

    • for in 便历出来的是属性
    • for of 遍历的是value
    • 手动给对象添加属性后, for in 是可以将新添加的属性遍历出来 但是for of 不行
    • for in 的属性是使用[]不可以使用 “.” eg: data[‘index’] instead of data.index

模板字符串

模板字符串使用``声明,支持

  • 在内容中出现换行 例如
    let a = '123\n  456\n   789';
    console.log(a);
    let b = `123
      456
       789`;
    console.log(b);
    let c = '123
      456
       789';
    console.log(c);
    
    输出分别是
    123
      456
       789
    123
      456
       789
    报错
    
  • 支持变量拼接,使用${}
    let name = "Liu";
    let spk1 = `I'm `+name+`, Hello`
    let spk2 = `I'm ${
           name}, Hello`
    console.log(spk1)
    console.log(spk2)
    

简化对象写法

可以在{}中直接写对象,例如

let aaa = "aaa"
let bbb = "bbb"
console.log({
   aaa,bbb})
console.log({
   aaa: "aaa", bbb: "bbb"})
console.log({
   aaa, bbb, foo(){
   console.log("OK")}})
console.log({
   aaa: "aaa", bbb: "bbb", foo:function(){
   console.log("OK")}})

结果是

{aaa: "aaa", bbb: "bbb"}
{aaa: "aaa", bbb: "bbb"}
{aaa: "aaa", bbb: "bbb", foo: ƒ}
{aaa: "aaa", bbb: "bbb", foo: ƒ}

这里要简写的是变量,不能是常量,例如我想构造{"A":"A"}不能写{"A"}

箭头函数

function(a,b)=>{//code}简写为(a,b)=>{//code}

  • this是静态的,始终指向函数声明时所在作用域下的this(call,apply修改对 他无效),而funcion是this指向调用者
      S.prototype.work1=function(){
         
        setTimeout(function(){
         console.log(this)},1000)
    }
    
    S.prototype.work2=function(){
         
        setTimeout(()=>{
         console.log(this)},1000)
    }
    
    S.prototype.work3=()=>{
         
        setTimeout(()=>{
         console.log(this)},1000)
    }
    
    let s=new S();
    s.age = 12;
    s.work1();
    s.work2();
    s.work3();
    
    输出
    window
    s对象
    window
    
  • 不能作为构造函数实例化对象,因为this不能指向对象,会报错XX不是一个构造函数
  • 不能使用arguments变量
    function work1(){
         console.log(arguments)}
    function work2(...arg){
         console.log(arg)}
    work3=()=>{
         console.log(arguments)}
    work4=(...arg)=>{
         console.log(arg)}
    work1(1,2,3,4)    // 输出Arguments变量
    work2(1,2,3,4)    // 输出数组
    work4(1,2,3,4)    // 输出数组
    work3(1,2,3,4)    // 报错arguments是undefined
    
  • 箭头函数还可以简写
    • 当只有一个形参的时候可以把(a)=>{// code}简写成a=>{// code}
    • 当代码体只有一条语句的时候()=>{// onecode}简写成()=>// onecode,同时不能写return,此时语句的返回结果就是返回值,例如(a)=>{return a*a}简写为a=>a*a
  • 特例,我想简写返回对象x => { foo: x }会报错,换成x => ({ foo: x })

实例 不适合与this有关的操作,例如dom的回调

let [btn1,btn2] = document.querySelectorAll("button");
btn1.myflag=true;
btn1.onclick=function(){
  setTimeout(function(){
    console.log(this.myflag);
  },1000)
}
btn2.myflag=true;
btn2.onclick=function(){
  setTimeout(()=>{
    console.log(this.myflag);
  },1000)
}

点击第一个按钮是undefined,第二个是true

获取所有奇数

let s = [1,4,5,6,7,8]
console.log(s.filter(i=>i%2))

函数默认参数

  • 与解构赋值结合
    function foo({
          url=127,port=22}={
          }){
         
      console.log(url,port)
    }
    foo({
         url:128})
    foo({
         port:23})
    foo({
         lalala:128})
    foo()
    

REST参数

对于function定义的函数可以使用arguments获取参数列表,arguments是一个伪数组,没有forEach等函数,我们可以使用REST参数解决,写法是…变量,

function foo(...args){
   
  console.log(args)
}
foo(1,2,3,4);   // 结果是[1,2,3,4]

与C语言的…一样,我们也可以指定一部分,但是…必须放末尾

function foo(x,y,...args){
   
  console.log(args)
}
foo(1,2,3,4);   // 结果是[3,4]

…Spread扩展运算符

与REST的…标识一样,作用不同,rest是放在形参的位置,扩展运算符是放在调用实参的位置,用来将数组分开(类似于解构数组)

function foo(){
   
    console.log(arguments)
}
foo(...[1,2,3])   //Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]

扩展运算符只能用在函数调用时候,但是也包括如写用法

// 1. 数组的合并
let ary = [...[1,2,3],...[4,5,6],...[7,8,9]]
// [1,2,3,4,5,6,7,8,9]

// 2. 数组的克隆
let aty_cp = [...ary]
// 当然这是个浅拷贝

// 3. 伪数组的转换
function foo(){
   
  let agms = [...arguments]
  console.log(agms)
}
foo(1,2,3,4,5)

...实际上是个语法糖

Symbol 数据类型

  • Symbol是ES6引入的一种新的数据类型
  • 用来表示独一无二的值
  • 他是一种类似于字符串的值,保证值是唯一的
  • Symbol值不能参与任何一种运算,外部也看不到Symbol的值是多少, 只能知道分别定义两个Symbol一定是不同的

创建Symbol

let s = Symbol()    // 不用写new 因为是js的默认数据类型
console.log(s,typeof s)     // Symbol() symbol

我们无法知道Symbol的值,js保证内部实现独一无二

我们还可以为Symbol传入一个注释

let s1 = Symbol("Liu");
let s2 = Symbol("Liu");
console.log(s1===s2)     // false

但是相同的注释不是生成相同的结果,这个功能一般用于调试使用, 例如想为对象加入一个debug熟悉就可以Obj[Symbol(debug)]="OK",方便我们删除,在ES10中会有新方法对注释进行利用

我们可以像使用hash一样为相同的内容生成相同的Symbol

let s1 = Symbol.for("Liu");
let s2 = Symbol.for("Liu");
console.log(s1===s2)     // true

Symbol的作用原文

Symbol的作用非常的专一,换句话说其设计出来就只有一个目的——作为对象属性的唯一标识符,防止对象属性冲突发生。

举个例子,你看上了公司前来的前台妹纸,想了解关于她的更多信息,于是就询问Hr同事,扫地阿姨,于是得到类似这样信息:

let info1 = {
   
    name: '婷婷',
    age: 24,
    job: '公司前台',
    description: '平时喜欢做做瑜伽,人家有男朋友,你别指望了'
}
let info2 = {
   
    description: '这小姑娘挺好的,挺热情的,嘿嘿嘿……'
}

显然,你需要对这两个数据进行汇总,结果,就会发现,描述都用了同一个对象属性description,于是整合的时候,就容器冲突,覆盖,导致“人家有男朋友”这么重要的信息都没注意到。

但是,如果要是Symbol,则完全就不要担心这个问题了:

let info1 = {
   
    name: '婷婷',
    age: 24,
    job: '公司前台',
    [Symbol('description')]: '平时喜欢做做瑜伽,人家有男朋友,你别指望了'
}
let info2 = {
   
    [Symbol('description')]: '这小姑娘挺好的,挺热情的,嘿嘿嘿……'
}

此时,我们对info1, info2对象进行复制,如下:

let target = {
   };
Object.assign(target,
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Liukairui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值