ECMASript 6笔记

2 篇文章 0 订阅

ECMASript 6

1

ECMASript 6新特性

8

let 关键字

18

let 关键字用来声明变量,使用 let 声明的变量有几个特点:

1.不允许重复声明
let star="罗志祥"
let star="小猪"

image-20210717200610852

2.块儿级作用域(即只在代码块里面有效)

JS中作用域有:全局作用域、函数作用域。没有块作用域的概念。ECMAScript 6(简称ES6)中新增了块级作用域。

块作用域由 { } 包括if,else,while,for语句里面的{ }也属于块作用域。

{
 let girl="周扬青";
}
  console.log(girl);

image-20210717201502460

ES6 允许块级作用域的任意嵌套。

{{{{
  {let insane = 'Hello World'}
  console.log(insane); // 报错
}}}};

上面代码使用了一个五层的块级作用域,每一层都是一个单独的作用域。第四层作用域无法读取第五层作用域的内部变量

3.不存在变量提升

var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。

为了纠正这种现象,let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。

image-20210717203215832

image-20210717203056741

4.不影响作用域链
作用域

作用域,就是变量起作用的区域(范围)

JS的变量作用域分为:全局作用域和函数作用域(局部作用域)

作用域链

作用域链是指:当js编译器在寻找变量时,先在最近的作用域(花括号)里找,如果找不到,则抄上一级作用域(花括号)里找,依次类推,直到找到或者找不到为止。这就是作用域链。

let v1=10;
   function f1() {
       let v2=20;
       if(true){
           let v3=30;
           console.log(v1);
       }
   }
   f1()

image-20210717211628984

应用场景:以后声明变量使用 let 就对了

const 关键字

19

const 关键字用来声明常量,const 声明有以下特点:

1.声明必须赋初始值

image-20210718082648360

2.标识符一般为大写(潜规则,不做硬性要求)
3.值不允许修改

image-20210718083024245

image-20210718082913720

4.不允许重复声明
5.块儿级作用域

image-20210718083259796

注意: 对象属性修改和数组元素变化不会出发 const 错误
本质

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于**复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。**因此,将一个对象声明为常量必须非常小心。应用场景:声明对象类型使用 const,非对象类型声明选择 let

变量的解构赋值

6

数组的解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

以前,为变量赋值,只能直接指定值。

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

ES6 允许写成下面这样

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

上面代码表示,可以从数组中提取值,按照对应位置,对变量赋值.本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。如果解构不成功,变量的值就等于undefined。

  let [foo, [[bar], baz]] = [1, [[2], 3]];
    console.log(foo);
    console.log([[bar], baz]);

image-20210718084749217

 let [foo] = [];
    let [bar, p] = [1];
    console.log([foo]);
    console.log([bar, p]);

image-20210718085043294

对象的解构赋值

对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。如果解构失败,变量的值等于undefined

 let obj={
        a:1,
        b:2,
        loc: {
            start: {
                line: 1,
                column: 5
            }
        },
        friends:[{
            name:"cyy2",
            age:20
        },{
            name:"cyy3",
            age:30
        },{
            name:"cyy4",
            age:40
        }]
    };
    // 如果出现对象属性名重复的情况,会报错,解决方法是使用: 来定义别名
    //如果声明的变量名和对象属性名一致,那就可以简写
    let {a,b,loc:{start:s1, start: {line:l1,column:c1}},
        friends:f1,friends:[{name:n1,age:ag1},{name:n2,age:ag2},{name:n3,age:ag3}]}=obj;

    console.log(a);          console.log(b);
    console.log(s1);         console.log(l1);
    console.log(c1);         console.log(f1);
    console.log(n1);         console.log(ag1);
    console.log(n2);         console.log(ag2);
    console.log(n3);         console.log(ag3);

image-20210718103941559

模板字符串

14

模板字符串(template string)是增强版的字符串,用反引号(``)标识,

特点:

1.字符串中可以出现换行符

2.在反引号(``)里面写${变量名}字符串

 //es6引入新的声明字符串的方式反引号(``)
    let s=`反引号也可以定义字符串`
    console.log(s,typeof s);
//反引号(``)字符串中可以出现换行符,其他的'',""不行
    let str = `<ul>
            <li>沈腾</li>
            <li>玛丽</li>
            <li>魏翔</li>
            <li>艾伦</li>
            </ul>`;
    console.log(str);
    // 变量拼接
    let star = '王宁';
    //以前变量和字符串拼接是使用+
    let r=star+'在前几年离开了开心麻花'
    console.log(r);
    //es6在反引号(``)里面写${变量名}字符串
    let result = `${star}在前几年离开了开心麻花`
    console.log(result);

image-20210718111456886

对象的简化写法

10

ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。

属性的简洁表示法

如果声明的变量名和对象属性名一致,那就可以简写

let s=`反引号也可以定义字符串`
    //简写形式:变量名和对象属性名一样
    const str={
        s
    }
    console.log(str);
    //es5
    const str1={
        s1:s
    }
    console.log(str1);

image-20210718114240161

对象里面的方法简写
//es6把方法中的:function省略了
const o = {
  method() {
    return "Hello!";
  }
};

// 等同于

const o = {
  method: function() {
    return "Hello!";
  }
};

注意:对象简写形式简化了代码,所以以后用简写就对了

箭头函数

5

ES6 允许使用「箭头」(=>)定义函数。

//es6箭头函数小括号是参数,花括号写实体内容
let fn = (arg1, arg2, arg3) => {
 return arg1 + arg2 + arg3;
}
//普通的写法
let fn = function(arg1, arg2, arg3) {
 return arg1 + arg2 + arg3;
}
箭头函数的注意点:
1.如果形参只有一个,则小括号可以省略
/**
* 2. 省略小括号的情况
*/
let fn2 = num => {
 return num * 10;
};
2.函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的 执行结果
/**
* 3. 省略花括号的情况
*/
let fn3 = score => score * 20;
3.箭头函数 this 实始终指向函数声明时所在作用域下 this 的值
普通函数中this

(1)总是代表着它的直接调用者,如obj.fn,fn里的最外层this就是指向obj

//hello直接调用者是obj,第一个this指向obj,setTimeout里匿名函数没有直接调用者,this指向window
const obj = {
    num: 10,
   hello: function () {
    console.log(this);    // obj
    setTimeout(function () {
      console.log(this);    // window
    });
   }    
}
obj.hello();

(2)默认情况下,没有直接调用者,this指向window

//hello是全局函数,没有直接调用它的对象,也没有使用严格模式,this指向window
function hello() { 
   console.log(this);  // window 
}  
hello();

(3)严格模式下(设置了’use strict’),this为undefined

function hello() { 
   'use strict';
   console.log(this);  // undefined
}  
hello();

(4)当使用call,apply,bind(ES5新增)绑定的,this指向绑定对象

ES6箭头函数中this

(1)默认指向定义它时,所处上下文的对象的this指向。即ES6箭头函数里this的指向就是上下文里对象this指向,偶尔没有上下文对象,this就指向window

//hello直接调用者是obj,第一个this指向obj,setTimeout箭头函数,this指向最近的函数的this指向,即也是obj
const obj = {
    num: 10,
   hello: function () {
       
    console.log(this);
       // obj
    setTimeout(() => {
      console.log(this);    // obj
    });
       
   }    
}
obj.hello();

//diameter是普通函数,里面的this指向直接调用它的对象obj。perimeter是箭头函数,this应该指向上下文函数this的指向,这里上下文没有函数对象,就默认为window,而window里面没有radius这个属性,就返回为NaN。
const obj = {
  radius: 10,  
  diameter() {    
      return this.radius * 2
  },  
    
  perimeter: () => 2 * Math.PI * this.radius
}
console.log(obj.diameter())    // 20
console.log(obj.perimeter())    // NaN

(2)即使是call,apply,bind等方法也不能改变箭头函数this的指向

4.箭头函数不能作为构造函数实例化
   let Person = (name, age)=>{
        this.name = name
        this.age=age;
    }
    let me = new Person('张三',30);
    console.log(me);

image-20210718124302091

5.不能使用 arguments

rest 参数(其它参数,,,,,…theArgs或… args)

13

ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments

Rest就是为解决传入的参数数量不一定, rest parameter(Rest 参数) 本身就是数组,数组的相关的方法都可以用。

你可以将rest参数定义为(其它参数,,,,,…theArgs或… args)

…theArgs或… args必须放在最后

image-20210718131452969

image-20210718131340898

扩展运算符(…)

17

扩展运算符(spread)也是三个点(…)。它好比 rest 参数的逆运算,将一 个数组转为用逗号分隔的参数序列,对数组进行解包。

  let boys = ['德玛西亚之力','德玛西亚之翼','德玛西亚皇子'];
    function fn(){
        console.log(arguments);
    }
    fn(...boys)

image-20210718135453908

应用

数组合并

  let skillOne = {
        q: '致命打击',
    };
    let skillTwo = {
        w: '勇气'
    };
    let skillThree = {
        e: '审判'
    };
    let skillFour = {
        r: '德玛西亚正义'
    };
    let gailun = {...skillOne, ...skillTwo,...skillThree,...skillFour};

    console.log(gailun); 

image-20210718135958113

Symbol 基本使用

15

ES5 的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是 ES6 引入Symbol的原因。

ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。

Symbol 值通过Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

 let s=Symbol("哈哈")
    console.log(s,typeof s);

    //注意,Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的。
    let s1=Symbol("哈哈")
    console.log(s===s1)

    // 有时,我们希望重新使用同一个 Symbol 值,Symbol.for()方法可以做到这一点
    let s3 = Symbol.for('哈哈');
    let s4 = Symbol.for('哈哈');
    console.log(s3 === s4);

image-20210718143525976

Symbol 特点

  1. Symbol 的值是唯一的,用来解决命名冲突的问题

  2. Symbol 值不能与其他数据进行运算

  3. Symbol 定义 的 对象属 性 不能 使 用 for…in 循 环遍 历 ,但 是可 以 使 用 Reflect.ownKeys 来获取对象的所有键名

CommonJS模块规范

20

CommonJS 概述

Node.js 应用由模块组成,每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。

CommonJS 规范还规定,每个模块内部有两个变量可以使用,require 和 module。

require 用来加载某个模块

module 代表当前模块,是一个对象,保存了当前模块的信息。exports 是 module 上的一个属性,保存了当前模块要导出的接口或者变量,使用 require 加载的某个模块获取到的值就是那个模块使用 exports 导出的值


// a.js
var name = 'morrain'
var age = 18
module.exports.name = name
module.exports.getAge = function(){
    return age
}
 
//b.js
var a = require('a.js')
console.log(a.name) // 'morrain'
console.log(a.getAge())// 18
CommonJS 之 exports

为了方便,Node.js 在实现 CommonJS 规范时,为每个模块提供一个 exports的私有变量,指向 module.exports。你可以理解为 Node.js 在每个模块开始的地方,添加了如下这行代码。


var exports = module.exports

于是上面的代码也可以这样写:


// a.js
var name = 'morrain'
var age = 18
exports.name = name
exports.getAge = function(){
    return age
}

有一点要尤其注意,exports 是模块内的私有局部变量,它只是指向了 module.exports,所以直接对 exports 赋值是无效的,这样只是让 exports 不再指向module.exports了而已。

CommonJS 之 require

require 命令的基本功能是,读入并执行一个 js 文件,然后返回该模块的 exports 对象。如果没有发现指定模块,会报错。

第一次加载某个模块时,Node.js 会缓存该模块。以后再加载该模块,就直接从缓存取出该模块的 module.exports 属性返回了。


// a.js
var name = 'morrain'
var age = 18
exports.name = name
exports.getAge = function(){
    return age
}
// b.js
var a = require('a.js')
console.log(a.name) // 'morrain'
a.name = 'rename'
var b = require('a.js')
console.log(b.name) // 'rename'

Module 的语法

2

模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。

模块化的好处 模块化的优势有以下几点:

  1. 防止命名冲突
  2. 代码复用
  3. 高维护性

模块化规范产品 ES6 之前的模块化规范有:

  1. CommonJS => NodeJS、Browserify
  2. AMD => requireJS
  3. CMD => seaJS

ES6 模块化语法 模块功能主要由两个命令构成:export 和 import。

  1. export 命令用于规定模块的对外接口
  2. import 命令用于输入其他模块提供的功能

一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。使用方式是,可以将export放在任何变量,函数或类声明的前面,从而将他们从模块导出

另外,export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。

使用export命令定义了模块的对外接口以后,其他 JS 文件就可以通过import命令加载这个模块。

image-20210718164113194

es6.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script type="module">
    //type="module"一定要加,不加会出现Uncaught SyntaxError: Cannot use import statement outside a module
    //如果想为输入的变量重新取一个名字,import命令要使用as关键字,将输入的变量重命名。
    //后缀名,js最好不要省掉可能报错
    import { firstName, lastName, age,multiply,streamV1,streamV2,streamLatestVersion as streamV3 } from '../js/es6.js';
   /* 这是的import命令,可以用任意名称指向es6.js输出的方法,这时就不需要知道原模块输出的函数名。
需要注意的是,这时import命令后面,不使用大括号。*/
    import sss from '../js/es6.js'
    console.log(`我叫${firstName}${lastName},今年${age}`)

   const m=multiply(1,4)
    console.log(m);

   streamV1();
   streamV2();
   streamV3();
    sss.foo();
    sss.bar();
</script>
</body>
</html>

es6.js

// 分别暴露
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var age = 20;
//export命令除了输出变量,还可以输出函数或类(class)
export function multiply(x, y) {
    return x * y;
}

//统一暴露
/*下面代码在export命令后面,使用大括号指定所要输出的一组变量。它与前一种写
法(直接放置在var语句前)是等价的,但是应该优先考虑使用这种写法。因为这样就可以在脚本尾部,一眼看清楚输出了哪些变量。*/
// export { firstName, lastName, age ,multiply};





// 下面代码使用as关键字,重命名了函数v1和v2的对外接口。重命名后,v2可以用不同的名字输出两次。
function v1() {console.log('你好') }
function v2() {console.log('大胆')  }

export {
    v1 as streamV1,
    v2 as streamV2,
    v2 as streamLatestVersion
};

// 默认暴露
// 默认暴露的方式只允许有一个: export default {}且在主模块引入时可以使用定义变量来接收的方式!
/*使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。
 为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。*/
export default {
    foo() {
        console.log('默认暴露方式')
    },
    bar() {
        console.log('默认暴露')
    }
}

image-20210718165514036

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值