es6重要内容用法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了es6重要内容用法相关的知识,希望对你有一定的参考价值。
ES6
一、ECMA历史
组成部分: ECMA、DOM、BOM
-
什么是ECMA?全称 ECMAScript 简写 ECMA 或 ES
ECMA是一个标准,JS是实现
例如: html5 是标准,chrome,FF,IE10是实现
将来也可能有 xxxscript 实现ECMA
-
目前的版本:
- 低级浏览器: 主要支持es3.1,3.2
- 高级浏览器: 正从ES5过度到ES6
-
版本进化过程
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正在制定草案
-
兼容性:
目前为止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
- 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定义的变量仅能够在之后使用
为什么需要块级作用域?
-
内层变量可能会覆盖外层变量。
var tmp = new Date(); function f() { console.log(tmp); if (false) { var tmp = ‘hello world‘; } } f();
-
用来计数的循环变量泄露为全局变量。
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
}
-
自执行函数封闭作用域,可以用块作用域替代
// 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一旦声明变量,就必须立即初始化,不能留到以后赋值。
-
const的作用域与let命令相同:只在声明所在的块级作用域内有效。
if (true) { const MAX = 5; } MAX
三、解构赋值
-
什么是解构赋值? 左边一种结构,右边一种结构,左右一一对应进行赋值
-
分类
-
数组解构赋值 **
-
对象解构赋值 **
-
字符串解构赋值
-
布尔值解构赋值
-
函数参数解构赋值
-
数值解构赋值
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);
}
以上是关于es6重要内容用法的主要内容,如果未能解决你的问题,请参考以下文章