ES6入门
整理了ES6常用的一些语法,跟大家分享(promise、generator什么的还没有梳理清楚,后续再更新。。。)
1⃣️ 变量声明-let 与 const
(首先关于测试结果:这里有个小问题,如果用let/const声明的变量,在控制台调试的话,第一次输出结果后,第二次如果你还想用,要么把代码放入编辑器中,再打开浏览器看结果,要么就把变量名更改重新输入结果,否则是会报错的)
let与const的作用与var 类似,都是用来声明变量但是在实际应用中,它俩有各自的特殊用途
(注意:ES6里let和const没有变量的提升,一定要声明后再使用,但代码编译成ES5之后,变量提升依旧存在)
先举个栗子
var name = 'aaron'; if(true) {
var name = 'peter';
console.log(name); // peter
} console.log(name); //peter
我们可以看到,使用var声明的变量,两次输出结果都是peter,那是因为ES5里只有全局作用域和函数作用域,没有块级作用域,那么我们怎么才能让它两次打印的结果分别是aaron 和 peter呢? 现在let就可以派上用场了
改造一下上面的栗子
let name = 'aaron'; if(true) {
let name = 'peter';
console.log(name); // peter
} console.log(name); //aaron
现在可以看到,两次的结果已经不相同了,let实际上为
JavaScript新增了块级作用域。用它所声明的变量,只在let
命令所在的代码块内有效。
下面再来看一发关于关于for循环的栗子,问题就是用来计数的循环变量泄露为全局变量,会对我们的一些操作带来很大的影响,话不多说,来看栗子
var a = [];
for (var i = 0; i <; i++) {
a[i] = function() {
console.log(i)
};
}
a[6](); //10
原本我们的需求是 a[6](),结果可以输出6,但无论我们写的是a[i](),最终输出的结果都是10,因为for循环结束之后,i的值已经变成了10,而i又是全局变量,当函数之行的时候,首先在函数体内部没有i这么一个变量,所以它会去上一级作用域去寻找,本栗中它的上一级作用域就是全局作用域,所以也就找到了已经变为10的全局变量i,所以a[i]();无论你[]内写0~9哪个数字,最终输出结果都是10;
在没有ES6之前,如果我们想让它的输出就过就是6,就要使用到闭包(闭包这东西,个人的理解,用大白话说就是把你想要实现功能的方法,外面再给它包一个函数。内部return你要实现功能的方法,由于函数的作用域,这样可以避免变量泄露变成全局变量,从而带来一些我们不想看到的结果)
var a = [];
function fn(i){
function inner() {
console.log(i);
}
return inner;
}
for (var i = 0; i <; i++) {
a[i] = fn (i);
}
a[6](); //6
讲真,这样很麻烦有没有?现在有了ES6 的let ,完全可以不用这么写了
var a = [];
for (let i = 0; i <; i++) {
a[i] = function() {
console.log(i)
};
}
a[6](); //6
只是改了几个字母,var改成了let,已经实现了我们的需求,很方便有没有?!
const
也用来声明变量,但是声明的是常量。一旦声明,常量的值就不能改变。改变的话,浏览器会报错
栗子
const A = 1;
A = 2; // Uncaught TypeError: Assignment to constant variable.
针对const的这个特性,我们可以在引用第三方库的时,把需要声明的变量,用const来声明,这样可以避免未来不小心重命名而导致出现bug
const xxx = require('xxxxx');
注意:当值为基础数据类型时,那么这里的值,就是指值本身。
而当值对应的为引用数据类型时,那么这里的值,则表示指向该对象的引用。这里需要注意,正因为该值为一个引用,只需要保证引用不变就可以,我们仍然可以改变该引用所指向的对象。
栗子
const obj = {
a: 20,
b: 30
} obj.a = 30;
obj.c = 40; console.log(obj); // Object {a: 30, b: 30,c:40}
这种情况下只要不是直接覆盖obj的值,只改变属性什么的还是还可以
2⃣️模版字符串
使用 反引号``(键盘上esc下面那个键) 将整个字符串包裹起来,而在其中使用 ${} 来包裹一个变量或者一个表达式
// es5
var a = 20;
var b = 30;
var string = a + "+" + b + "=" + (a + b); // es6
const a = 20;
const b = 30;
const string = `${a}+${b}=${a+b}`;
3⃣️解构(destructuring)赋值
数组以序列号一一对应,这是一个有序的对应关系。
对象根据属性名一一对应,这是一个无序的对应关系。
为了更好的理解,直接上栗子吧
数组的解构赋值
// es5
var arr = [1, 2, 3];
var a = arr[0];
var b = arr[1];
var c = arr[2]; // es6
const arr = [1, 2, 3];
const [a, b, c] = arr;
console.log(a,b,c) // 1,2,3
对象的解构赋值
const MYOBJ = {
className: 'trigger-button',
loading: false,
clicked: true,
disabled: 'disabled'
}
现在我们想要取得其中的2个值:loading与clicked:
// es5
var loading = MYOBJ.loading;
var clicked = MYOBJ.clicked; // es6
const { loading, clicked } = MYOBJ;
console.log(loading);// false // 还可以给一个默认值,当props对象中找不到loading时,loading就等于该默认值
const { loadings = false, clicked } = MYOBJ;
console.log(loadings);// false
4⃣️展开运算符(spread operater)
在ES6中用...
来表示展开运算符,它可以将数组方法或者对象进行展开。上栗子
1.函数调用中使用展开运算符
函数调用里,将一个数组展开成多个参数,我们会用到apply:
function test(a, b, c) { }
var args = [0, 1, 2];
test.apply(null, args);
在ES6里可以这样写
function test(a,b,c) { }
var args = [0,1,2];
test(...args);
2.数组字面量中使用展开运算符
有了ES6,我们可以直接加一个数组直接合并到另外一个数组当中
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 10, 20, 30]; // 这样,arr2 就变成了[1, 2, 3, 10, 20, 30];
展开运算符也可以用在push函数中,可以不用再用apply()函数来合并两个数组:
var arr1=['a','b','c'];
var arr2=['d','e'];
arr1.push(...arr2); //['a','b','c','d','e']
3.用于解构赋值
let [arg1,arg2,...arg3] = [1, 2, 3, 4];
arg1 //1
arg2 //2
arg3 //['3','4']
注意:解构赋值中展开运算符只能用在最后,否则会报错
4.展开运算符可以将伪数组变成真正的数组
var list=document.querySelectorAll('div');
var arr=[..list];
Object.prototype.toString.apply(list) // "[object NodeList]"
Object.prototype.toString.apply(arr) // "[object Array]"
关于对象展开
好像目前ES6还不支持这样,现在这样写浏览器会报错,ES7草案里貌似有提到,所以对象展开这里先了解一下就好了
const obj1 = {
a: 1,
b: 2,
c: 3
} const obj2 = {
...obj1,
d: 4,
e: 5,
f: 6
} // 结果类似于 const obj2 = Object.assign({}, obj1, {d: 4,e:5,f:6})
扩展:Object.assign()
方法用于将所有可枚举的属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。 语法:Object.assign(target, 一个或多个sources)
5⃣️ arrow function箭头函数
函数的快捷写法,不需要通过 function
关键字创建函数,并且还可以省略 return
关键字。(注意:箭头函数本身没有this,如果在箭头函数内使用this,这个this一定是它上级的this,再有就是箭头函数可以代替函数表达式,但代替不了函数声明,它还是需要声明才能使用的)。
(parma)=>{expression},箭头函数根据parma个数的不同,写法上还可以做如下改变
() => { expression } // 零个参数用 () 表示
x => { expression } // 一个参数可以省略 ()
(x, y) => { expression } // 多参数不能省略 ()
注意: 在ES6中,会默认采用严格模式,因此this也不会自动指向window对象了,而箭头函数本身并没有this,因此this就只能是undefined,这一点,在使用的时候,一定要慎重慎重再慎重,不然踩了坑你都不知道自己错在哪!这种情况,如果你还想用this,就不要用使用箭头函数的写法。
栗子
var person = {
name: 'tom',
getName: function() {
return this.name;
}
} // 用ES6的写法来重构上面的对象
const person = {
name: 'tom',
getName: () => this.name
} // 但是编译结果却是
var person = {
name: 'tom',
getName: function getName() {
return undefined.name;
}
};
对上面的代码稍作改动
const person = {
name: 'tom',
getName: function() {
return setTimeout(() => this.name, 1000);
}
} // 编译之后变成
var person = {
name: 'tom',
getName: function getName() {
var _this = this; // 使用了我们在es5时常用的方式保存this引用 return setTimeout(function () {
return _this.name;
}, 1000);
}
};
6⃣️函数参数的默认值
之前我们想要保证传入函数的参数有一个默认值,通常需要这么写
function add(x) {
var x = x || 20;
return x;
} console.log(add()); // 20
但这种方法是有缺陷的,比如说我们如果传入一个false
function add(x) {
var x = x || 20;
return x;
} console.log(add(false)); // 20
打印结果是20 而不是fasle,显然合格结果不是我们想要的,如果我们想要打印出false,就还要再做什么if判断等一些列操作,很麻烦,现在有了es6,我们可以很容易解决这个问题,下面我们来看一下es6的写法
function add(x = 20) {
return x ;
} console.log(add());// 20
console.log(add(false)); // false
可以看到,es6很容易就解决了这个问题。
7⃣️对象字面量({})扩展
ES6针对对象字面量做了许多简化语法的处理
1)精简属性:
const name = 'Jane';
const age = 20 // es6写法
const person = {
name,
age
} // es5写法
var person = {
name: name,
age: age
};
2)精简方法:
// es6写法
const person = {
name,
age,
getName() { // 只要不使用箭头函数,this就还是我们熟悉的this
return this.name
}
} // es5写法
var person = {
name: name,
age: age,
getName: function getName() {
return this.name;
}
};
3)属性名表达式:(这里有点儿恶心,经过几次代码测试,最终确定下面这样解释的话,可能会容易理解一些)
在对象字面量中可以使用中括号作为属性,表示属性也能是一个变量了,而且这个变量的值还可以改变
const name = 'Jane'; const person = {
[name]: true,
['a'+'ge']: true
}
注意:上面的对象{}内写了两个[]属性 ,切记[]里面如果是一个变量的话,那么这个变量一定要是一个已经声明过的,否则结果就是undefined,[]如果是表达式,那么访问的时候,要向下面这样写
console.log(person['a'+'ge'])/console.log(person['age'])/console.log(oerson.age) // true
console.log(person[name]);// true 注意:对象内用[变量]当作属性时,访问该属性只能用[]语法,对象内给这个属性赋什么值,它就会变成什么值,而且这个值也可以通过[]里面传入访问变量最初设置的值,也可以访问到,写就是说像下面这样写 和上面结果是一样的
console.log(person['Jane']); // true
对象的方法也可以这样写
let obj = {
['h'+'ello']() {
return 'hi';
}
};
console.log(obj.hello()); // hi
8⃣️class、extend、super
class、extend、super这三个特性涉及了ES5中最令人头疼的的几个部分:构造函数、继承,原型...
ES6提供了更接近传统语言的写法,引入了Class(类)这个概念。新的class写法让对象原型的写法更加清晰、更像面向对象编程的语法,也更加通俗易懂。
新旧语法对比
class
// ES5
// 构造函数
function Person(name, age) {
this.name = name;
this.age = age;
} // 原型方法
Person.prototype.getName = function() {
return this.name
} // ES6
class Person {
constructor(name, age) { // 构造函数
this.name = name;
this.age = age;
} getName() { // 原型方法
return this.name
}
}
上面代码首先用class
定义了一个“类”,可以看到里面有一个constructor
方法,这就是构造方法,而this
关键字则代表实例对象。
简单地说,constructor
内定义的方法和属性是实例对象自己的,而constructor
外定义的方法和属性则是所有实例对象可以共享的。这个和ES5里的构造函数是差不多的意思,相当于把方法定义在构造函数里是私有的,而把方法定义到原型中,所有实例共享
extend继承
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
} getName() {
return this.name
}
} // Student类继承Person类
class Student extends Person {
constructor(name, age, gender, classes) {
super(name, age);
this.gender = gender;
this.classes = classes;
} getGender() {
return this.gender;
}
}
Class之间可以通过extends
关键字实现继承,这比ES5的通过修改原型链实现继承,要清晰和方便很多。上面定义了一个Cat类,该类通过extends
关键字,继承了Animal类的所有属性和方法。
super
关键字,它指代父类的实例(即父类的this对象)。子类必须在constructor
方法中调用super
方法,否则新建实例时会报错。这是因为子类没有自己的this
对象,而是继承父类的this
对象,然后可以对其进行加工。如果不调用super
方法,子类就得不到this
对象。
关于 super,像上面的栗子
// 构造函数中
// es5写法
Person.call(this);
// es6写法
super(name, age);
class、extend/super三者的综合实栗
class Animal {
constructor(){
this.type = 'animal'
}
says(say){
console.log(this.type + ' says ' + say)
}
} let animal = new Animal()
animal.says('hello') //animal says hello class Cat extends Animal {
constructor(){
super()
this.type = 'cat'
}
} let cat = new Cat()
cat.says('hello') //cat says hello
9⃣️模块的 Import 和 Export
import
用于引入模块,export
用于导出模块。
// 引入整个文件
import dva from 'dva'; // 引入函数(可以是一个或多个)
import { connect } from 'dva';
import { Link, Route } from 'dva/router'; // 引入全部并作为 github 对象
import * as github from './services/github'; // 导出默认
export default App;
// 部分导出,复合写法是 export { App } from './file';
等价于import { App } from './file;export{App}
ES6入门的更多相关文章
- ES6入门笔记
ES6入门笔记 02 Let&Const.md 增加了块级作用域. 常量 避免了变量提升 03 变量的解构赋值.md var [a, b, c] = [1, 2, 3]; var [[a,d] ...
- es6入门4--promise详解
可以说每个前端开发者都无法避免解决异步问题,尤其是当处理了某个异步调用A后,又要紧接着处理其它逻辑,而最直观的做法就是通过回调函数(当然事件派发也可以)处理,比如: 请求A(function (请求响 ...
- es6入门3--箭头函数与形参等属性的拓展
对函数拓展兴趣更大一点,优先看,前面字符串后面再说,那些API居多,会使用能记住部分就好. 一.函数参数可以使用默认值 1.默认值生效条件 在变量的解构赋值就提到了,函数参数可以使用默认值了.正常我们 ...
- Vue+koa2开发一款全栈小程序(1.课程介绍+2.ES6入门)
1.课程介绍 1.课程概述 1.做什么? Vue+koa2开发一款全栈小程序 2.哪些功能? 个人中心.图书列表.图书详情.图书评论.个人评论列表 3.技术栈 小程序.Vue.js.koa2.koa- ...
- es6入门5--class类的基本用法
在ES6之前,准确来说JavaScript语言并无类的概念,却有模拟类的做法.相比在类似java这类传统面向对象语言中通过类来生成实例,js则通过构造函数模拟类来生成实例. 这是因为在JS设计初期,作 ...
- es6入门6--数组拓展运算符,Array.from()基本用法
本文只是作为ES6入门第九章学习笔记,在整理知识点的同时,会加入部分个人思考与解答,若想知道更详细的介绍,还请阅读阮一峰大神的ES6入门 一.拓展运算符 ES6中新增了拓展运算(...)三个点,它的作 ...
- ES6入门之let和const命令
前言 大家好,我是一只流浪的kk,当你看到这边博客的时候,说明你已经进入了ES6学习的领域了,从本篇博客开始,我将会将自己学习到ES6的相关知识进行整理,方便大家参考和学习,那么我将带你进入第一节的内 ...
- ES6入门之变量的解构赋值(二)
前言 在上一章 ES6入门之let和const命令中我们对ES6的相关语法已经有了初步了解,上一章中我们主要学习了三大部分的内容,let命令的使用,块级作用域,const命令的使用,那么从本篇博客将进 ...
- ES6入门十二:Module(模块化)
webpack4打包配置babel7转码ES6 Module语法与API的使用 import() Module加载实现原理 Commonjs规范的模块与ES6模块的差异 ES6模块与Nodejs模块相 ...
- es6入门7--Set Map数据结构
本文作为ES6入门第十三章的学习整理笔记,可能会包含少部分个人的理解推测,若想阅读更详细的介绍,还请阅读原文ES6入门 一.set数据结构 1.set不接受重复值 ES6新增了Set构造函数用于创建s ...
随机推荐
- iOS10构建版本不显示的问题
iOS10,构建版本问题: 在Xcode中->product->archive,进行相关操作后,upload后没有报错验证也成功的情况下,在开发者账号构建版本号里面迟迟没有显示的原因: i ...
- struct 和typedef struct的区别
和int char一样struct也是一种数据类型,也可以声明变量--结构变量. 定义结构体变量的一般格式为: struct 结构名 { 类型 变量名; 类型 变量名; ... }结构变量; 另一种常 ...
- cordova原理与插件制作
---恢复内容开始--- cordova插件打包教程: http://www.jianshu.com/p/96855e009e95 www.itnose.net/detail/6245407.html ...
- boost.asio源码阅读(1) - 从chat_server开始
1. 关于示例代码 chat 先从简单的入手, 在如下路径:boost_1_63_0/libs/asio/example/cpp11/chat中找到chat_server.cpp 查看其成员, pri ...
- (8)集合之List,ArrayList,LinkedList
集合的体系结构 Collection 单列集合的接口 |----List 如果实现了List接口的集合类,具备的特点是有序,可重复 |----Set 如果实现了Set接口的集合类,集合特点无序不可重复 ...
- SQL Server数据库读取数据的DateReader类及其相关类
之前学了几天的SQL Server,现在用C#代码连接数据库了. 需要使用C#代码连接数据库,读取数据. 涉及的类有: ConfigurationManage SqlConnection SqlCom ...
- C# 6 与 .NET Core 1.0 高级编程 - 41 ASP.NET MVC(下)
译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 41 ASP.NET MVC(下)),不对的地方欢迎指出与交流. 章节出自<Professional C# ...
- linux 私房菜 CH8 linux 磁盘与文件系统管理
索引式文件系统 superblock 记录此系统的整体信息,包括 inode/block 的总量.使用量.剩余量,以及文件系统的格式与相关信息等: inode 记录档案的属性,一个档案占用一个 ino ...
- Jenkis Editable Email Notification Plugin 使用介绍
Jenkis Editable Email Notification Plugin 使用介绍 前言 Jenkins本身提供的Email插件功能实在有限,只能提供当前Job的基本信息,比如成功.失败以及 ...
- java实现微信红包分配算法
红包算法分析 有人认为,抢红包的额度是从0.01到剩余平均值*N(N是一个系数,决定最大的红包值)之间,比如一共发了10块钱,发了10个红包:第一个人可以拿到(0.01~1*N)之间的一个红包值,当然 ...