ES6快速入门使用
https://www.jianshu.com/p/061304806bda
Babel-webpack的配置
前段项目我想使用ES6的语法我应该怎么做呢?我们可以查看Babel的官方文档,就简单用webpack如何配置
所以我们就可以先用ES6语言来写代码,然后用webpack打包生成ES5的文件,下面只是简单介绍一下,详细的可以查看官方文档,当然了这只是一种工具,我们只需要看官网怎么做的就可以
1. Shell
npm install --save-dev babel-loader babel-core
2. webpack.config.js
module: {
rules: [
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }
]
}
3. create .babelrc
npm install babel-preset-env --save-dev
//JSON
{
"presets": ["env"]
}
var let const
- var 可声明前置
var a
a = 1
var a = 2
ES6 新增了let
命令,用来声明变量。它的用法类似于var
,但也有区别:
- let 不存在变量提升
console.log(bar); // 报错ReferenceError
let bar = 2;
a = 1 //报错
let a
- let不允许在相同作用域内,重复声明同一个变量。
// 报错
function func() {
let a = 10;
var a = 1;
}
// 报错
function func() {
let a = 10;
let a = 1;
}
let a = 3
var a =4 //报错
let a =5 //报错
- 存在块级作用域
for(let i =0;i<3;i++){
console.log(i)
}
console.log(i) //报错
块级作用域的出现,实际上使得获得广泛应用的立即执行函数表达式(IIFE)不再必要了。
(function(){
var a = 1
})()
==>
{
let a = 1
}
ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。
- 内层变量可能会覆盖外层变量。
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world'; // var tmp 变量提升
}
}
f(); // undefined
- 用来计数的循环变量泄露为全局变量。
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]); // i泄露为全局变量
}
console.log(i); // 5
- 暂时性死区(TDZ)
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
- const
const声明一个只读的常量。一旦声明,常量的值就不能改变。
const一旦声明变量,就必须立即初始化,不能留到以后赋值。
//基本类型
const PI = 3.1415;
PI // 3.1415
PI = 3; // TypeError: Assignment to constant variable.
//引用类型
const foo = {};
// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123
// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only
适用let的也适用const
解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
- 数组的解构赋值
let [a,b,c] = [1,2,3]
console.log(a,b,c) // 1 2 3
let [a, [b], c] = [1, [2], 3]
a // 1
b // 2
c // 3
let [x, , y] = [1, 2, 3] // x=1 y=3
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
如果解构不成功,变量的值就等于undefined。
let [foo] = [];
let [bar, foo] = [1];
// 报错
let [foo] = 1;
默认值
解构赋值允许指定默认值。
数组对应值有没有?如果没有(没有指undefined),使用默认值,有就使用对应值
let [foo = true] = [];
foo // true
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
let [a=2,b=3] = [undefined, null]
a //2
b //null
- 对象的解构赋值
实际上说明,对象的解构赋值是下面形式的简写
let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };
let { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
let { bar, foo } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"
let { baz } = { foo: "aaa", bar: "bbb" };
baz // undefined 没有同名的
对象解构的默认值
默认值生效的条件是,对象的属性值严格等于undefined。
var {x = 3} = {};
x // 3
var {x, y = 5} = {x: 1};
x // 1
y // 5
var {x: y = 3} = {};
y // 3
var {x: y = 3} = {x: 5};
y // 5
var { message: msg = 'Something went wrong' } = {};
msg // "Something went wrong"
- 字符串的解构赋值
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。
let {length : len} = 'hello';
len // 5
- 数值和布尔值的解构赋值
解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。
let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError
- 函数参数的解构赋值
function add([x, y] = [1,1]){
return x + y;
}
add() // 2
add([2]) // 3
add([1, 2]); // 3
function sum({x,y} = {x:0, y:0},{a=1,b=1}){
return [x+a,y+b]
}
console.log(sum({x:1,y:2},{a:2})) //[3,3]
- 解构赋值的作用
- 交换变量的值
let x = 1;
let y = 2;
[x, y] = [y, x]; // [2,1]
- 函数参数默认值
function ajax(url , type='GET'){
}
ajax(url:'http://localhost')
字符串常用
- 字符串模板
// ES5字符串拼接
$('#result').append(
'There are <b>' + basket.count + '</b> ' +
'items in your basket, ' +
'<em>' + basket.onSale +
'</em> are on sale!'
);
模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。
$('#result').append(`
There are <b>${basket.count}</b> items
in your basket, <em>${basket.onSale}</em>
are on sale!
`);
模板字符串中嵌入变量,需要将变量名写在${}之中
function authorize(user, action) {
if (!user.hasPrivilege(action)) {
throw new Error(
// 传统写法为
// 'User '
// + user.name
// + ' is not authorized to do '
// + action
// + '.'
`User ${user.name} is not authorized to do ${action}.`);
}
}
数组扩展常用
- 扩展运算符
扩展运算符(spread)是三个点(...)
var a = [1,2]
console.log(...a) // 1,2
var b = [...a,3]
b // [1,2,3]
function add(x, y) {
return x + y;
}
const numbers = [4, 38];
add(...numbers) // 42
... 应用替代apply用法
// ES5 的写法
Math.max.apply(null, [14, 3, 77])
// ES6 的写法
Math.max(...[14, 3, 77])
// ES5的 写法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
Array.prototype.push.apply(arr1, arr2);
// ES6 的写法
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1.push(...arr2);
函数参数的扩展
function sort(...arr){
console.log(arr.sort())
}
sort(3,1,5) //[1,3,5]
Array.form()
- Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)。
// NodeList对象
let ps = document.querySelectorAll('p');
Array.from(ps).forEach(function (p) {
console.log(p);
});
// arguments对象
function foo() {
var args = Array.from(arguments);
// ...
}
// 类数组对象
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
函数扩展
- 可以给参数添加默认值
function log(x, y = 'World') {
console.log(x, y);
}
log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello
//练习,区别?
// 写法一
function m1({x = 0, y = 0} = {}) {
return [x, y];
}
// 写法二
function m2({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
// 函数没有参数的情况
m1() // [0, 0]
m2() // [0, 0]
// x 和 y 都有值的情况
m1({x: 3, y: 8}) // [3, 8]
m2({x: 3, y: 8}) // [3, 8]
// x 有值,y 无值的情况
m1({x: 3}) // [3, 0]
m2({x: 3}) // [3, undefined]
// x 和 y 都无值的情况
m1({}) // [0, 0];
m2({}) // [undefined, undefined]
m1({z: 3}) // [0, 0]
m2({z: 3}) // [undefined, undefined]
//总结
ex1: 调用函数需要你传递一个对象,如果你没传对象就用默认值对象{},默认值对象里面都是 undefined, 所以属性使用初始值
ex2:参数需要是一个对象,如果没传对象,就用默认值对象{ x: 0, y: 0 }如果传了对象,就使用你传递的对象
- 箭头函数
- ES6 允许使用
“箭头”(=>)
定义函数。
- ES6 允许使用
var f = v => v;
//等价于
var f = function(v) {
return v;
};
var f = () => 5;
// 等同于
var f = function () { return 5 };
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
return num1 + num2;
};
如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。
var sum = (num1, num2) => { return num1 + num2; }
- 箭头函数的this
函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。this对象的指向是可变的,但是在箭头函数中,它是固定的。
function foo() {
setTimeout(() => {
console.log('id:', this.id);
}, 100);
}
var id = 21;
foo.call({ id: 42 });
// id: 42
setTimeout
的参数是一个箭头函数,这个箭头函数的定义生效是在foo函数生成时,而它的真正执行要等到 100 毫秒后。如果是普通函数,执行时this应该指向全局对象window
,这时应该输出21。但是,箭头函数导致this总是指向函数定义生效时所在的对象(本例是{id: 42})
,所以输出的是42
。
对象扩展
- 属性的简洁表示法
ES6 允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
const foo = 'bar';
const baz = {foo};
baz // {foo: "bar"}
// 等同于
const baz = {foo: foo};
function f(x, y) {
return {x, y};
}
// 等同于
function f(x, y) {
return {x: x, y: y};
}
f(1, 2) // Object {x: 1, y: 2}
//方法简写
const o = {
method() {
return "Hello!";
}
};
// 等同于
const o = {
method: function() {
return "Hello!";
}
};
Module的语法 模块化
模块功能主要由两个命令构成:export和import
。export
命令用于规定模块的对外接口,import
命令用于输入其他模块提供的功能。
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export
关键字输出该变量。下面是一个 JS 文件,里面使用export
命令输出变量。
// profile.js
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export {firstName, lastName, year};
//usage.js
import {firstName, lastName, year} from './profile';
export命令除了输出变量,还可以输出函数或类(class)。
export function multiply(x, y) {
return x * y;
};
- export default 命令
使用import
命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载,为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default
命令,为模块指定默认输出。
// export-default.js
export default function () {
console.log('foo');
}
其他模块加载该模块时,import
命令可以为该匿名函数指定任意名字。
// import-default.js
import customName from './export-default';
customName(); // 'foo'
Class和继承
ES6 的class
可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以
做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。上面的代码用 ES6 的class改写,就是下面这样。
//定义类
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
//等价于
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.toString = function () {
return '(' + this.x + ', ' + this.y + ')';
};
var p = new Point(1, 2);
ES6 的类,完全可以看作构造函数的另一种写法。
class Point {
// ...
}
typeof Point // "function"
Point === Point.prototype.constructor // true
构造函数的prototype属性,在 ES6 的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype属性上面。
class Point {
constructor() {
// ...
}
toString() {
// ...
}
toValue() {
// ...
}
}
// 等同于
Point.prototype = {
constructor() {},
toString() {},
toValue() {},
};
constructor
方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
class Point {
}
// 等同于
class Point {
constructor() {}
}
- Class静态方法
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static
关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
class Foo { //类
static classMethod() {
return 'hello';
}
}
Foo.classMethod() // 'hello'
var foo = new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function
上面代码中,Foo类的classMethod方法前有static关键字
,表明该方法是一个静态方法,可以直接在Foo类上调用
(Foo.classMethod()),而不是在Foo类的实例上调用。如果在实例上调用静态方法,会抛出一个错误,表示不存在该方法。
- 继承
Class 可以通过extends
关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。
class Point {
}
class ColorPoint extends Point {
}
super 关键字
super
这个关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
console.log( `hello, ${this.name}, i am ${this.age} years old`);
}
}
class Student extends Person {
constructor(name, age, score) {
super(name, age);
this.score = score;
}
sayScore() {
console.log( `hello, ${this.name}, i am ${this.age} years old, i get ${this.score}`);
}
}
ES6快速入门使用的更多相关文章
- ES6快速入门(二)数据结构
ES6快速入门 一.解构 1. 对象解构 let person = { name: 'Tang', age: 28 }; //必须同名,必须初始化 let {name, age} = person; ...
- ES6快速入门(一)函数与作用域
ES6快速入门 一.块级绑定 1.var声明与变量提升 使用var声明的变量,不论在何处都会被视为(声明)在函数级作用域顶部的位置发生. function getValue(condition) { ...
- python 全栈开发,Day88(csrf_exempt,ES6 快速入门,Vue)
BBS项目内容回顾 1. 登陆页面 1. 验证码 1. PIL(Pillow) 2. io 2. ORM 1. 增删改查 3. AJAX $.ajax({ url: '', type: '', dat ...
- es6 快速入门 系列
es6 快速入门(未完结,持续更新中...) 前言 为什么要学习es6 es6对于所有javaScript开发者来说,非常重要 未来,es6将构成javaScript应用程序的基础 es6中很多特性, ...
- es6 快速入门 —— 函数
其他章节请看: es6 快速入门 系列 函数 函数是所有编程语言的重要组成部分,es6之前函数语法一直没什么变化,遗留了许多问题,javaScript开发者多年来不断抱怨,es6终于决定大力度更新函数 ...
- es6 快速入门 系列 —— 变量声明:let和const
其他章节请看: es6 快速入门 系列 变量声明:let和const 试图解决的问题 经典的 var 声明让人迷惑 function demo1(v){ if(v){ var color='red' ...
- es6 快速入门 系列 —— promise
其他章节请看: es6 快速入门 系列 Promise Promise 是一种异步编程的选择 初步认识Promise 用 Promise 来实现这样一个功能:发送一个 ajax,返回后输出 json ...
- es6快速入门 系列 - async
其他章节请看: es6 快速入门 系列 async 前文我们已经知道 promise 是一种异步编程的选择.而 async 是一种用于执行异步任务更简单的语法. Tip:建议学完 Promise 在看 ...
- es6 快速入门 系列 —— 类 (class)
其他章节请看: es6 快速入门 系列 类 类(class)是 javascript 新特性的一个重要组成部分,这一特性提供了一种更简洁的语法和更好的功能,可以让你通过一个安全.一致的方式来自定义对象 ...
- es6 快速入门 系列 —— 对象
其他章节请看: es6 快速入门 系列 对象 试图解决的问题 写法繁杂 属性初始值需要重复写 function createPeople(name, age){ // name 和 age 都写了 2 ...
随机推荐
- Maven 多套环境配置
在Java开发中会配置不同环境,可通过Maven的profile指定不同的环境配置,pom.xml配置如下: <project xmlns="http://maven.apache.o ...
- 树莓派学习笔记——GPIO功能学习
0.前言 树莓派现在越来越火,网上树莓派的资料也越来越多.树莓派的学习可以分为linux系统学习和linux驱动学习,利用树莓派制作LED流水灯应该算是驱动学习吧.树莓派来自国外,国外嵌入式开 ...
- Java创建和读取Json
在Java中构造和解析JSON我用的是org.json,附件为相应的org.json.jar. 下面是两个函数,一个是创建JSON,一个是从文本构造JSON并解析之. 创建json: //constr ...
- 使用Kotlin创建Android项目
如果你已经使用过Android Studio和Gradle,那么这一章会比较简单.我不会给出很多细节和截图,因为用户界面和细节可能会一直变化. 我们的应用是由一个简单的天气app组成,正如所使用的Go ...
- 2019pycharm破解大法
通过激活码激活Pycharm 1 先找到你的hosts文件: Windows电脑:c:\windows\system32\drivers\etc Linux/Mac电脑:/etc 2 编辑hosts文 ...
- push和unshift方法
push和unushift都是向数组插入元素. push是向数组尾部插入元素. unshift是向数组头部插入元素. 共同点:都可以一次插入多个元素. arrayObject.push(newelem ...
- POI-word转html
package com.test.poiword; import android.app.Activity; import android.os.Bundle; import android.webk ...
- 纯JS写的2048游戏,分享之
这几天玩儿着2048这个游戏,突然心血来潮想练习下敲代码的思路.于是乎就模仿做了一个,到眼下位置还没有实现动态移动,不是非常好看,只是玩儿着自己模仿的小游戏还是蛮爽的,哈哈 假设没有玩儿过这个游戏,最 ...
- Linux程序存储结构与进程结构 堆和栈的差别
摘要:本文主要讲述了Linux系统中.程序存储结构(代码区.数据段和BBS区)与进程的基本结构(代码区.数据段.BBS区.堆和栈).以及堆和栈的差别. Linux程序存储结构与进程结构 1.Linux ...
- lspci查看硬件信息时提示找不到命令
系统环境:centos 6.3 X64 错误信息:[root@localhost ~]# lspci-bash: lspci: command not found 问题原因:这是因为没有安装pciut ...