目录
let注意点
1.不存在变量提升。
2.不允许重复声明 。
3.暂时性死区。只要块级作用域内存在let
命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。例如下面代码:
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
存在全局变量tmp
,但是块级作用域内let
又声明了一个局部变量tmp
,导致后者绑定这个块级作用域,所以在let
声明变量前,对tmp
赋值会报错。 “暂时性死区”也意味着typeof
不再是一个百分之百安全的操作(在let tmp前使用typeof tmp也会报错)。
4.循环体内能重复使用const、let在每次循环中定义同一个变量:因为它每次循环相当于不同的代码块(产生不同的局部变量,也可以理解每一次循环结束后回收了变量,每次循环都是独立的),所以每次都可以再次定义同一个变量,但一次循环中是不能定义2次的同一个变量。
let i = 10
for(let i = 1; i < 5; i++){
let i = 1;console.log(i) // i始终输出为1
}
解构
利用相同的数据结构将对象或数组的中的变量取出来。用法如下:
let {name,age}={name:'pyf',age:18};
此时相当于外部申明了name,age并赋值,注意解构为对象时属性名要对应相同。
重命名
通过冒号后加新名称可以重命名,name和age将不会被定义。
let {name:n,age:a}={name:'pyf',age:18};
默认值
当解构的变量中没有值或值为undefined时(值会null时不会赋予默认值),此时会赋予默认值,例如下面a的为默认值16.
let {name:n,age:a=16}={name:'pyf'};
解构给已有变量
需要在语句的最外面套一层大括号来避免语句中的大括号当做块级作用域。
let name,age;
({name:n,age:a}={name:'pyf',age:18});
多层解构
只会将最里面层的内容解构出来。
let {a:{b}}={a:{b:12}}
//a=undefined,b=12
ESM模块化
通过在script标签加上属性type="module"来实现。
有些浏览器例如IE6不能识别模块化,可以通过babel转换,import文件通过ajax去引入,然后通过babel转换。通过引入下面的模块实现。
注意:需要添加nomodule属性(只有当浏览器不支持模块化时才会执行脚本)实现,不然会导致导入导出的内容执行2遍。
<script nomodule src="https://unpkg.com/promise-polyfill@8.2.3/dist/polyfill.min.js"></script>
<script nomodule src="https://unpkg.com/browser-es-module-loader@0.4.1/dist/browser-es-module-loader.js"></script>
<script nomodule src="https://unpkg.com/browser-es-module-loader@0.4.1/dist/babel-browser-build.js"></script>
和commonjs区别
CommonJs和es6的Module的区别_风流倜傥唐伯虎的博客-CSDN博客_怎么判断是es6模块还是mjs
模块化注意点
1.每个script标签下的内容都是私有作用域(未实现模块化时,是共享全局作用域)。
2.import导入的文件即使在同一目录下,也需要通过./进行导入,不能直接写文件名。
3.导出的模块文件会被执行一遍,当所有非异步语句执行完后才会导出(自动将导出语句置于最后),相当于直接把导出文件内容移到import语句处执行且import语句处不会等导入文件中的异步请求执行完在往下走。
4.默认采用严格模式(use strict)。
5.会自动延迟执行脚本(相当于在script上添加defer属性),在dom渲染完后才运行脚本(通常会阻塞dom渲染,script脚本通常会放到html底部)。
6.通过CORS去请求外部JS模块的,所以需要布到服务器上打开,不然会报CORS错误,VScode可以通过下载Liver Server插件解决。
export、export default语法
导出的方式有以下几种,1、2、3都可以同时使用,只要导出的内容不重复即可。
1.在变量的申明前或表达式创建前添加关键字export。例如下面代码:
export let a1;
export const a2 =2;
export let a3 = function(){}
export class Person {}
2.通过export {a1,a2,a3}添加,a1,a2,a3为变量名,中间用逗号隔开。
3.通过export default 变量名或申明函数或类(注意表达式不行),一个模块中只能有一个export default。使用方法单独对应imort中的第三条。
4.可以通过as对导出的变量进行重命名export { a1 as aa},此时导出的变量名为aa。
5.导入后集中导出。
export { default as Button } from './button.js'
export { Avatar } from './avatar.js'
import语法
import有两种功能:引入模块和引入css文件。
文件必须带文件格式前缀 / ./ ../
不能省略扩展名也不会自动引入index.js文件(在打包工具作用下可以,引入文件夹时相当于引入该文件夹下的index.js文件)。
下面a.js和b.js在一个文件目录下,我们在a模块中导入b模块(b中导出了变量a1,a2,a3,...,an),写多条相同的也只会导入一次。
1.a模块中可以使用import {a1,a2,a3} from './b'导入变量a1,a2,a3,注意导入导出的变量需要同名。
2.a模块中可以使用import * as obj from './b'导入所有b模块中导出的变量a1,a2,a3,...,an,访问时通过obj.a1访问a1。
3.通过import 变量名 from './b'导入模块b中默认export default导出的变量。注意不用加{}且变量名可以自己取,不用相同。
// 方法一(常用) 其中aa为export default导出的变量名
import a as aa , { b } from './module.js'
// 方法二 其中aa为export default导出的变量名
import { b, default as aa } from './module.js'
4.无论通过什么申明的变量导出,导入后都是只读的。
5.import ‘./module.js’直接引入相当于只执行了引入的文件。
import函数动态导入、
提供了import函数来进行动态导入 ,下面module对象上挂载了导出的成员(then中的module参数相当于import * as module from './module.js')
import('./module.js').then(module => {})
对象属性扩展写法
允许字面量定义对象时,用表达式作为对象的属性名,即把表达式放在方括号内。
let lastWord = 'last word';
const a = {
'first word': 'hello',
[lastWord]: 'world',
['first'+' '+ lastword]:'last first'
};
a['first word'] // "hello"
a[lastWord] // "world"
a['last word'] // "world"
a['first last world'] // 'last first'