es6重要内容用法

📅 2026/7/30 11:15:49 👁️ 阅读次数 📝 编程学习
es6重要内容用法

###ES6

####一、ECMA历史

>组成部分: ECMA、DOM、BOM

1. 什么是ECMA?全称 ECMAScript 简写 ECMA 或 ES

ECMA是一个标准,JS是实现

例如: HTML5 是标准,chrome,FF,IE10是实现

将来也可能有 xxxscript 实现ECMA
2. 目前的版本:

1. 低级浏览器: 主要支持es3.1,3.2
2. 高级浏览器: 正从ES5过度到ES6
3. 版本进化过程

1996 ES1.0 js稳定 Netscape将js提交给ECMA组织
1998 ES2.0 正式发布
1999 ES3.0 浏览器广泛支持
2007 ES4.0 ES4过于激进,被废除
2008 ES3.1 4.0变为缩水版的3.1 代号:Harmony
2009 ES5.0 ES5 正式发布,同时公布了javascript.next-6.0前身
2011 ES5.1 成为ISO国际标准
2013.3 ES6.0 ES6.0制定草案
2013.12 ES6.0 发布草案
2015.6 ES6.0 ES6.0预计发布,同时发布 es7.0正在制定草案

4. 兼容性:

目前为止ES5 ES6支持情况还凑合

nodejs用的就是chrome内核,在node中已经可以使用es6的很多特性了

ES5和ES6已经逐渐沦为后台语言

------

1. 在浏览器中如何使用?需要编译工具,把ES6语法编译成ES5
babel
traceur ---google出的编译器
bootstrap 引导程序
<script src="traceur.js"></script>
<script src="bootstrap.js"></script>
<script type="module">
let a = 12;
</script>


<script src="https://traceur-compiler.googlecode.com/git/bin/traceur.js"
type="text/javascript"></script>
<script src="https://traceur-compiler.googlecode.com/git/src/bootstrap.js"
type="text/javascript"></script>
<script>
traceur.options.experimental = true;
</script>
<script type="module" src="js/calc.js"></script>

2. 在线编译:主要用于测试

a. babeljs.io/repl
b. google.github.io/traceur-compiler/demo/repl.html

3. 在node中可以直接使用

"use strict"
let a = 12;
console.log(a);

a. 直接用,需要添加 use strict
b. node --harmony_destructuring xx.js

---

###二、定义变量 let和const

1. ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。

> let定义的变量不能在相同作用域下,重复声明同一个变量

function () {
let a = 10;
var a = 1;
}

function () {
let a = 10;
let a = 1;
}

> 以下现象用来理解块级作用域

现象1:

{
let a = 10;
var b = 1;
}
console.log(a);
console.log(b);

> 结论:let声明的变量尽在 {}内有效

现象2: let声明的变量仅在当前作用域中有效

for(let i=0;i<10;i++){}
console.log(i);

现象3:

var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6]();
//========
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6]();
i是let声明的,所以当前的 i仅在本轮循环有效,直接会被解析成数字。

现象4:循环语句是父作用域,循环体是一个独立的作用域,互不影响。

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


现象5: 不存在变量提升

// var 的情况
console.log(foo);
var foo = 2;

// let 的情况
console.log(bar);
let bar = 2;

现象6: 暂时性死区

var tmp = 123;

if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}

报错:因为当使用let时,当前快作用域被封闭,let定义的变量仅能够在之后使用

#### 为什么需要块级作用域?

1. 内层变量可能会覆盖外层变量。

var tmp = new Date();

function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';
}
}
f();

2. 用来计数的循环变量泄露为全局变量。

var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}
console.log(i); // 5

#### 块级作用域试题
1.

function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5
}

2. 自执行函数封闭作用域,可以用块作用域替代

// IIFE 写法
(function () {
var tmp = ...;
...
}());

// 块级作用域写法
{
let tmp = ...;
...
}

3.

function f() { console.log('I am outside!'); }

(function () {
if (false) {
// 重复声明一次函数f
function f() { console.log('I am inside!'); }
}

f();
}());


### 二、const 声明一个只读的常量。一旦声明,常量的值就不能改变

> const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。

1. const的作用域与let命令相同:只在声明所在的块级作用域内有效。

if (true) {
const MAX = 5;
}
MAX

### 三、解构赋值

1. 什么是解构赋值? 左边一种结构,右边一种结构,左右一一对应进行赋值

2. 分类
* 数组解构赋值 **
* 对象解构赋值 **
* 字符串解构赋值
* 布尔值解构赋值
* 函数参数解构赋值
* 数值解构赋值

#### 1 解构赋值基本方式

let [x,y] = [1,2];
console.log(x,y);//1,2

#### 2 ...解构赋值

{
let a,b,rest;
[a,b,...rest] = [1,2,3,4,5,6];
console.log(a,b,rest);//rest [3,4,5,6]
}

#### 3 对象解构赋值

//对象的解构赋值
{
let a,b;
({a,b} = {a:1,b:2});
console.log(a,b);
}

#### 4 默认值(没有找到配对有默认值使用默认值,没有默认值值为 undefined)

// 解构赋值的默认值
{
let a,b,c,rest;
[a,b,c=3,d] = [1,2];
console.log(a,b,c,d);
}
#### 5 变量交换

//利用解构赋值交换变量中的值
{
let a = 1;
let b = 2;
[a,b] = [b,a];
console.log(a,b);
}

#### 6 函数返回多个值

function f(){
return [1,2];
}
let [a,b] = f();
console.log(a,b);

#### 7 选择性的接收 返回值

{
function f(){
return [5,6,7,8,9];
}
let [a,,,,b] = f();
console.log(a,b);
}

#### 8 我只关心第一个,其他的先放数组里

{
function f(){
return [5,6,7,8,9];
}
let [a,...b] = f();
console.log(a,b);
}

#### 9 对象结构赋值

{
let o = {name:'yuonly',age:20};
let {age,name} = o;
console.log(name,age);
}

#### 10 可以替代 arguments

// ... 可以替代arguments
{
function test3(...arg){
for(let v of arg){
console.log('rest',v);
}
}
test3(1,2,3,4,'a');
}


### 四、对象扩展

#### 1. 简洁表示法

//简洁表达
{
let a = 1;
let b = 2;
//ES5
let es5 = {
a:a,
b:b
}
console.log(es5);
//ES6
let es6 = {
a,
b
}
console.log(es6);

}
{
//如果有方法的处理方式
// ES5
let es5 = {
hello:function(){
console.log('hellow');
}
}
//ES6
let es6 = {
hello(){
console.log('hello');
}
}
}

#### 2. 属性表达式

let a = 'b';
let es5_obj = {//es5中对象的 key必须是固定的
a:'c'
}
//es6
let es6_obj = {//属性值可以是变量
[a] : 'c'
}
console.log(es6_obj,'es6_obj');

#### 3. 扩展运算符(ES7语法,支持不好,了解)

{
//babel不支持,无法编译
let {a,b,...c} = {a:'test',b:'kill',c:'ddd',d:'ccc'}
c = {
c:'ddd',
d:'ccc'
}
}

#### 4. object新增API

{
// is :判断两个值是否相等
console.log('字符串',Object.is('abc','abc'));
console.log('数组',Object.is([],[]));//两个不同的地址

//assign : 潜拷贝
console.log('拷贝',Object.assign({a:'a'},{b:'b'}));

// entries
let test = [k:123,o:456];
for(let [key,value] of Object.entries(test)){
console.log([key,value]);
}
}

### 五、类
#### 1 基本语法

{
//基本定义和生成实例
class Person{
constructor(name='laozhou'){
this.name = name;
}
}
let p1 = new Person('小王');
console.log('构造函数和实例',p1);
}

#### 2 类的继承

{
//继承
class Father{
constructor(name='laozhou'){
this.name = name;
}
}
class Child extends Father{

}
console.log('子类的实例',new Child());
console.log('子类自己传',new Child('小刘'))

}


{
//子类如何覆盖父类的值
class Father{
constructor(name='laozhou'){
this.name = name;
}
}
class Child extends Father{
constructor(name='child'){
//this.type = 'boy';//super必须在第一行,否则报错
super(name);//调用父亲类的构造函数
this.type = 'boy';
}
}
console.log('子类覆盖父类属性的实例',new Child());
}

#### 3 静态属性

//静态属性
{
class Person{
constructor(name='laozhou'){
this.name = name;
}
}
//静态属性的定义,是直接给类下的属性赋值,该属性就是静态属性
Person.type = 'text';//type就是静态属性
}

#### 4 静态方法

//静态方法
{
class Person{
constructor(name='laozhou'){
this.name = name;
}
static tell(){//相当于原型下的方法,是属于类本身的,用类来调用
console.log('tell');
}
}
Person.tell();
}


#### 5 getter-setter

{
//getter setter
class Father{
constructor(name='laozhou'){
this.name = name;
}
//此处longName不是函数而是属性,相当于新增了一个属性 longName
get longName(){
return 'yu_'+this.name;
}
set longName(value){
this.name = value;
}
}

let f1 = new Father();
console.log('getter',f1.longName);
f1.longName = 'hello';
console.log('setter',f1.longName);
}

### 六、promise
> promise是异步变成的解决方案(解决回调地狱)

#### 1 基本写法

{
//es5 中的异步操作
let ajax = function(callback){
console.log('执行');
setTimeout(function(){
callback && callback.call();
},1000);
}
ajax(function(){
console.log('timeout1');
})
}

{
//ES6
let ajax = function(){
console.log('执行2');
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve();//resolve后会有then方法,执行后续操作
},1000);
})
}
ajax().then(function(){
console.log('promise','timeout');
})
}

#### 2 promise.all 所有的 异步操作都成功后,在去执行一个动作。例子,图片都加在完成之后再显示到页面

//promise.all :把多个promise实例当做一个promise实例,当所有的状态都完成之后,才会触发新的promise对象的then方法

//应用,比如广告中有三张图,需要三张图都加载再去更新dom
{
//所有图片加载完成在加载页面
function loadImg(src){
return new Promise((resolve,reject)=>{
let img = document.createElement('img');
img.src = src;
img.onload = function(){
resolve(img);
}
img.onerror = function(){
reject(err);
}
})
}

function showImg(imgs){
imgs.forEach(function(img){
document.body.appendChild(img);
})
}

Promise.all([
loadImg('https://img10.360buyimg.com/n4/s260x260_jfs/t3079/363/6070979658/42126/5b5c2f39/589af086N4a3bed39.jpg'),
loadImg('https://img14.360buyimg.com/n4/s260x260_jfs/t4345/284/2534342556/119746/550dee37/58d34a9dNf0bd717f.jpg'),
loadImg('https://img13.360buyimg.com/n4/s260x260_jfs/t3259/170/5587914266/144572/64259fc5/5873347aN14e34822.jpg'),
]).then(showImg);

}

#### 3 promise.race 谁先到加载谁

{
//promise.race 谁先回来处理谁,先到先得
function loadImg(src){
return new Promise((resolve,reject)=>{
let img = document.createElement('img');
img.src = src;
img.onload = function(){
resolve(img);
}
img.onerror = function(){
reject(err);
}
})
}

function showImgs(img){
let p = document.createElement('p');
p.appendChild(img);
document.body.appendChild(p);
}

Promise.race([
loadImg('https://img10.360buyimg.com/imgzone/jfs/t5149/215/1247256617/226900/c371168/590dcc2bN2234f761.jpg'),
loadImg('https://img14.360buyimg.com/n4/s260x260_jfs/t4345/284/2534342556/119746/550dee37/58d34a9dNf0bd717f.jpg'),
loadImg('https://img13.360buyimg.com/n4/s260x260_jfs/t3259/170/5587914266/144572/64259fc5/5873347aN14e34822.jpg'),
]).then(showImgs);
}

#### 4 promise可以让代码执行的步骤更清晰,过程更可控

//使用promise后,更清晰
{
let oBox = document.getElementById('box');

function toWidth(w){
return new Promise(function(resolve,reject){
let timer = setInterval(function(){
var oldWidth = oBox.clientWidth;
if(oldWidth>w){
clearInterval(timer);
resolve();
}
oBox.style.width = oldWidth + 10 + 'px';
},100);
})
}

function toHeight(h){
return new Promise(function(resolve,reject){
let timer = setInterval(function(){
var oldHeight = oBox.clientHeight;
if(oldHeight>h){
clearInterval(timer);
resolve();
}
oBox.style.height = oldHeight + 10 + 'px';
},100);
})
}

function toSmall(size){
return new Promise(function(resolve,reject){
let timer = setInterval(function(){
var oldWidth = oBox.clientWidth;
var oldHeight = oBox.clientHeight;
if(oldWidth<size || oldHeight<size){
clearInterval(timer);
resolve();
}
console.log(123);
oBox.style.width = oldWidth - 10 + 'px';
oBox.style.height = oldHeight - 10 + 'px';
},100);
})
}

//使用promise后,更清晰,可以随意更改流程。
toHeight(400)
.then(function(){
return toWidth(600);
})
.then(function(){
return toHeight(300);
})
.then(function(){
return toSmall(100);
})
.then(function(){
return toHeight(400);
})
}

//ES5
{
function toWidth(w,callback){
let timer = setInterval(function(){
var oldWidth = oBox.clientWidth;
if(oldWidth>w){
clearInterval(timer);
callback && callback();
}
oBox.style.width = oldWidth + 10 + 'px';
},100);
}

function toHeight(h,callback){
let timer = setInterval(function(){
var oldHeight = oBox.clientHeight;
if(oldHeight>h){
clearInterval(timer);
callback && callback();
}
oBox.style.height = oldHeight + 10 + 'px';
},100);
}

function toSmall(size,callback){
let timer = setInterval(function(){
var oldHeight = oBox.clientHeight;
var oldWidth = oBox.clientWidth;
if(oldHeight<size){
clearInterval(timer);
callback && callback();
}
oBox.style.width = oldWidth - 10 + 'px';
oBox.style.height = oldHeight - 10 + 'px';
},100);
}

//代码可读性差,而且很难控制执行顺序
toWidth(500,function(){
toHeight(300,function(){
toSmall(100,function(){
toWidth(400,function(){
toHeight(100,function(){

})
})
});
})
});
}


### 七、模块化

#### 1. 基本概念:每一个文件都是独立的作用域,一个模块,都是独立存在,不会互相影响

#### 2. ES6模块化语法

##### 方式一: 优点:可以只导出部分模块。弊端,导出模块特别多的时候,不能一眼看出都导出了那些模块
//模块的导出 module1.js
export let a = 123;
export function test(){
console.log('test');
}
export class Hello{
test(){
console.log('class');
}
}
//模块的导入 entry.js
a as A 起别名 A,外部使用A来操作a
import {a as A,test,Hello} from './lesson/6.module/module1.js';

console.log(A,test,Hello);

//导入所有模块放入 obj对象下
import * as obj from './lesson/6.module/module1.js';
console.log(obj.a);

##### 方式二:推荐方式

//导出 module2.js
let num = 123;
let test = function(){
console.log('test');
}
class Person{
test(){
console.log('Person');
}
}
//1,批量导出,一目了然导出了那些东西给外部 2, 没有起名字,将命名权给倒入方。
export default {
num,
test,
Person
}


//导入 entry.js
import M from './lesson/6.module/module2.js';
console.log(M,M.num);
M.test()


### 八、函数扩展(箭头函数)

* 参数默认值
* rest参数
* 扩展运算符(rest参数的逆运用)
* 箭头函数
* 尾调用

#### 1 参数默认值

{
function test(x,y=10){
console.log('默认值',x,y);
}
test(1);
test(99,88);
}
// 有默认值的参数后面,不能有 没有默认值的参数
{
function test(x,y=10,c){//会报错,在默认值后面不能有 没有默认值的参数
console.log('默认值',x,y);
}
}
//函数的作用域
{
let x = 'test';
function test2(x,x=y){
console.log('作用域——',x,y);
}
test2('new');
}
//没有的时候用上面的
{
let x = 'test';
function test2(c,y=x){
console.log('作用域2',x,y);
}
test2('new');
}

#### 2 rest参数

{
//此时的arg相当于是 arguments
function test3(...arg){
for(let v of arg){
console.log('rest:',v);
}
}
test3(1,2,3,4,5);
}
#### 3 扩展运算符(rest参数的逆运用)


{
console.log(...[1,2,3]);
}

#### 4 箭头函数

{
let arrow = v=>v*10;
console.log(arrow(3));

<!-- let arrow2 = (v)=>{return v*50};
console.log(arrow2(2)); -->
}
相当于是
{
let arrow = function(v){
return v*10;
}
console.log(arrow(3));
}
#### 5 尾调用 :函数的最后一句话是函数,就是为调用

{
function tail(x){
console.log('tail',x);
}
function go(x){
return tail(x);
}
go(123);
}