ES6扫盲
原文阅读请点击此处
一、let和const
{ // let声明的变量只在let命令所在的代码块内有效 let a = 1; var b = 2; } console.log(a); // 报错: ReferenceError: a is not defined console.log(b);
// for循环的技术器就很适合let命令 for (let i = 0; i < 3; i++) { console.log(i); } console.log(i); // ReferenceError: i is not defined
// 这里的i是var声明的,在全局范围内有效,素偶一每一次循环,新的i值都会覆盖旧值,导致最后输出的是最后一轮的i值 for (var i = 0; i < 10; i++) { a[i] = function() { console.log(i); } } a[6](); // 10 var b = []; // 使用let声明的变量尽在块级作用域内有效,所以每一次循环的j其实都是一个新的变量,于是最后输出6 for (let j = 0; j < 10; j++) { a[j] = function() { console.log(j); } } b[6]();
// let不像var那样会发生"变量"提升的现象 // 但是经过babel转换器转换之后,还是存在变量提升的现象 // ES6明确规定,如果区块中存在let和const命令,则这个区块中对这些命令声明的变量从一开始就形成封闭作用域.只要在声明这些变量之前就使用这些变量,就会报错 { console.log(foo); // ReferenceError let foo = 2; } // 块级作用域 { // 块级作用域的出现使得获得广泛应用的立即执行匿名函数(IIFE)不再必要了 // IIFE写法 (function() { var tmp = 'a'; // ... })(); // 块级作用域写法 { let tmp = 'a'; // ... } // 因此,我们可以使用块级作用域来划分业务模块,以及避免全局变量 } { let a = 'secret'; function f() { return a; } } f(); // 报错
// const声明的常量不得改变值 // const一旦声明常量,就必须立即初始化,不能留到以后赋值 // const的作用域与let命令相同:只在声明所在的块级作用域内有效 // const命令声明的变量也不提升,只能声明后使用 const foo = 'AAA'; foo = 'BBB'; // 编译不通过
{ // 跨模块常量 // constants.js //export const A = 1; //export const B = 2; //export const C = 3; // test1.js模块 //import * as constants from 'constants'; }
// 全局对象的属性 var a = 1; console.log(window.a); // 1 let b = 2; console.log(window.b); // undefined
二、字符串
{ // 使用for of循环字符串 for (let c of 'foo') { console.log(c); } let s = 'Hello world!'; // 使用字符串的startsWidth/endsWidth/includes方法 console.log(s.startsWith('Hello')); // true console.log(s.endsWith('!')); // true console.log(s.includes('e')); // true // 这三个方法都支持第二个参数,表示开始搜索的位置 s.startsWith('world', 6); // true let person = { name: 'king', age: 20 }; // 模板字符串 // 所有的空格和缩进都会被保留在输出中 let str = (` The name is ${person.name}. The age is ${person.age}. `); console.log(str); }
三、函数
// 函数参数的默认值 function log(x, y = 'world') { console.log(x, y); } log('hello'); // 可以省略尾部参数的默认值 function f(x = 1, y) { return [x, y]; } f(); // [1, undefined] f(2); // [2, undefined] f(, 1); // 报错, 编译无法通过 // rest参数 function add(...values) { let sum = 0; for (let val of values) { sum += val; } return sum; } console.log(add(2, 5, 3)); // 10 const sortNumbers = function() { let arr = Array.prototype.slice.call(arguments); return arr.sort(); }; const sortNumbers = function (...numbers) { return numbers.sort(); }; sortNumbers(3, 1, 2); // rest参数必须是参数列表中的最后一个 const push = function(array, ...items) { items.forEach(function(item) { array.push(item); }); }; let a = []; console.log(push(a, 3, 1, 2));
四、对象
// Object.assign方法用来将源对象的所有可枚举属性复制到目标对象 let target = { a: 1 }; // 后边的属性值,覆盖前面的属性值 Object.assign(target, { b: 2, c: 3 }, { a: 4 }); console.log(target); // 用处1 - 为对象添加属性 class Point { constructor(x, y) { Object.assign(this, {x, y}); } } //let p = new Point(1, 2); // //console.log(p); // Point {x: 1, y: 2} // 用处2 - 为对象添加方法 Object.assign(Point.prototype, { getX() { return this.x; }, setX(x) { this.x = x; } }); let p = new Point(1, 2); console.log(p.getX()); // 1 // 用处3 - 克隆对象 function clone(origin) { return Object.assign({}, origin); }
五、Set和Map
// Set里面的成员的值都是唯一的,没有重复的值,Set加入值时不会发生类型转换,所以5和"5"是两个不同的值. let s = new Set(); [2, 3, 5, 4, 5, 2, 2].map(function(x) { s.add(x); }); //for (let i of s) { // console.log(i); //} console.log([...s]); console.log(s.size); // 数组去重 function dedupe(array) { return Array.from(new Set(array)); } console.log(dedupe([1, 2, 2, 3])); // 1, 2, 3
{ // Map类似于对象,也是键值对的集合,但是"键"的范围不限于字符串,各种类型的值(包括对象)都可以当做键. // 也就是说,Object结构提供了"字符串--值"的对应,Map的结构提供了"值——值"的对象,是一种更完善的Hash结构实现. var m = new Map(); var o = { p: 'Hello World' }; m.set(o, 'content'); m.get(o); // content m.has(o); // true m.delete(o); // true m.has(o); // false m.set(o, 'my content').set(true, 7).set('foo', 8); console.log(m); // Map/数组/对象 三者之间的相互转换 console.log([...m]); }
六、Iterator和Generator
{ // 是一种接口,为各种不同的数据结构提供统一的访问机制.任何数据结构,只要不输Iterator接口,就可以完成遍历操作. // 可供for...of循环消费 const arr = ['red', 'green', 'blue']; let iterator = arr[Symbol.iterator](); for (let v of arr) { console.log(v); // red green blue } for (let i of iterator) { console.log(i); } // for of 循环可以代替数组对象的forEach方法, 同样可以替代对象的for in循环 }
{ function * foo() { yield 1; yield 2; yield 3; yield 4; yield 5; return 6; } for (let v of foo()) { console.log(v); } }
七、Promise和async
{ let getJSON = function (path, param) { return new Promise(function(resolve, reject) { let async = typeof param.async == 'undefined' ? true : param.async; //let deferred = $.Deferred(); param = param || {}; param.data.auth_token = lib.getToken(); window.loading(); $.ajax({ url: path, data: param.data, type: 'POST', dataType: 'json', async: async, timeout: 15000, success: function (data) { window.unloading(); if (data.code == 0) { resolve.apply(this, [data]); } else { reject.apply(this, [data]); lib.alert(data.msg, '我知道了'); } }, error: function (xhr, type) { window.unloading(); reject.apply(this, ['网络异常, 请稍候再试']); lib.alert('网络异常, 请稍候再试'); } }); }); }; getJSON('/xxx.json').then(function(rep) { }).catch(function(rep) { }); }
{ function timeout(ms) { return new Promise(function(resolve) { setTimeout(resolve, ms); }); } async function asyncPrint(value, ms) { let promise = await timeout(ms); console.log(value); } asyncPrint('Hello world !', 1000); }
八、class
{ class Point { static classMethod() { return 'classMethod...'; } // constructor方法是类的默认方法,通过new命令生成对象实例时自动调用该方法. // 一个类必须有constructor方法,如果没有显示定义,一个空的constructor方法会被默认添加 constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } get prop() { return 'getter'; } set prop(value) { console.log('setter:' + value); } } // 静态属性的处理,只能用下面这种方式 Point.foo = 1; console.log(Point.foo); // 1 // 继承 class ColorPoint extends Point { constructor(x, y, color) { // super方法必须被调用, 否则编译不通过 // 如果super在赋值属性this.xx = xx,后边调用,会报错'this' is not allowed before super() super(x, y); this.color = color; } toString() { return 'The color is ' + this.color + ' and the point is ' + super.toString(); } } var p = new ColorPoint(1, 2, 'red'); console.log(p.toString()); p.prop = 1; p.prop; console.log(Point.classMethod()); // 父类的静态方法可以被子类继承 console.log('ColorPoint.classMethod(): ' + ColorPoint.classMethod()); }
九、Module
{ // module /** * 优势: * 1. ES6可以在编译时就完成模块编译,效率要比commonJs模块的加载方式高 * 2. 不再需要UMD模块格式,将来服务器端和浏览器都会支持ES6模块格式.目前,通过各种工具库其实已经做到了这一点 * 3. 将来浏览器的新API可以用模块格式提供,不再需要做成全局变量或者navigator对象的属性 * 4. 不再需要对象作为命名空间(比如Math对象),未来这些功能可以通过模块提供 */ }
// 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}; // export命令除了输出变量,还可以输出函数或类(class)。 export function multiply (x, y) { return x * y; }; // export输出的变量就是本来的名字,但是可以使用as关键字重命名。 function v1() { //... } function v2() { //... } export { v1 as streamV1, v2 as streamV2, v2 as streamLatestVersion }; // import // main.js import {firstName, lastName, year} from './profile'; // 重命名 import { lastName as surname } from './profile'; // import命令具有提升效果,会提升到整个模块的头部,首先执行。 foo(); import { foo } from 'my_module'; // 仅仅执行lodash模块,但是不输入任何值。 import 'lodash'; // export default // 为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。 // export-default.js export default function () { console.log('foo'); } // import-default.js // 需要注意,这时import命令后面,不使用大括号。 import customName from './export-default'; customName(); // 'foo' // export default命令用在非匿名函数前,也是可以的。 // export-default.js export default function foo() { console.log('foo'); } // 或者写成 function foo() { console.log('foo'); } export default foo;
十、编程风格
// 1. let取代var // 2. 全局常量 // 在let和const之间,建议优先使用const,尤其是在全局环境,不应该设置变量,只应设置常量。 // const声明常量还有两个好处,一是阅读代码的人立刻会意识到不应该修改这个值,二是防止了无意间修改变量值所导致的错误。 // 所有的函数都应该设置为常量。 // bad var a = 1, b = 2, c = 3; // good const a = 1; const b = 2; const c = 3; // best const [a, b, c] = [1, 2, 3]; // 3. 字符串 // 静态字符串一律使用单引号或反引号,不使用双引号。动态字符串使用反引号。 // 4. 对象 //对象尽量静态化,一旦定义,就不得随意添加新的属性。如果添加属性不可避免,要使用Object.assign方法。 // bad const a = {}; a.x = 3; // if reshape unavoidable const a = {}; Object.assign(a, { x: 3 }); // good const a = { x: null }; a.x = 3; // 对象的属性和方法,尽量采用简洁表达法,这样易于描述和书写。 var ref = 'some value'; // bad const atom = { ref: ref, value: 1, addValue: function (value) { return atom.value + value; }, }; // good const atom = { ref, value: 1, addValue(value) { return atom.value + value; }, }; // 5. 数组 //使用扩展运算符(...)拷贝数组。 // bad const len = items.length; const itemsCopy = []; let i; for (i = 0; i < len; i++) { itemsCopy[i] = items[i]; } // good const itemsCopy = [...items]; //使用Array.from方法,将类似数组的对象转为数组。 const foo = document.querySelectorAll('.foo'); const nodes = Array.from(foo); // 6. 函数 //不要在函数体内使用arguments变量,使用rest运算符(...)代替。因为rest运算符显式表明你想要获取参数,而且arguments是一个类似数组的对象,而rest运算符可以提供一个真正的数组。 // bad function concatenateAll() { const args = Array.prototype.slice.call(arguments); return args.join(''); } // good function concatenateAll(...args) { return args.join(''); } //使用默认值语法设置函数参数的默认值。 // bad function handleThings(opts) { opts = opts || {}; } // good function handleThings(opts = {}) { // ... } // 7. 模块 //首先,Module语法是JavaScript模块的标准写法,坚持使用这种写法。使用import取代require。 // bad const moduleA = require('moduleA'); const func1 = moduleA.func1; const func2 = moduleA.func2; // good import { func1, func2 } from 'moduleA'; //使用export取代module.exports。 // commonJS的写法 var React = require('react'); var Breadcrumbs = React.createClass({ render() { return <nav />; } }); module.exports = Breadcrumbs; // ES6的写法 import React from 'react'; const Breadcrumbs = React.createClass({ render() { return <nav />; } }); export default Breadcrumbs //如果模块只有一个输出值,就使用export default,如果模块有多个输出值,就不使用export default,不要export default与普通的export同时使用。 //不要在模块输入中使用通配符。因为这样可以确保你的模块之中,有一个默认输出(export default)。 // bad import * as myObject './importModule'; // good import myObject from './importModule'; //如果模块默认输出一个函数,函数名的首字母应该小写。 function makeStyleGuide() { } export default makeStyleGuide; //如果模块默认输出一个对象,对象名的首字母应该大写。 const StyleGuide = { es6: { } }; export default StyleGuide;
ES6扫盲的更多相关文章
- ES6 扫盲
原文地址:ECMAScript 6 扫盲--小胡子 1. let.const 和 block 作用域 let 允许创建块级作用域,ES6 推荐在函数中使用 let 定义变量,而非 var: var a ...
- 深度扫盲JavaScript的模块化(AMD , CMD , CommonJs 和 ES6)
原文地址 https://blog.csdn.net/haochangdi123/article/details/80408874 一.commonJS 1.内存情况 对于基本数据类型,属于复制.即会 ...
- ECMAScript 6 扫盲
ECMAScript 6 目前基本成为业界标准,它的普及速度比 ES5 要快很多,主要原因是现代浏览器对 ES6 的支持相当迅速,尤其是 Chrome 和 Firefox 浏览器,已经支持 ES6 中 ...
- 前端MVC Vue2学习总结(七)——ES6与Module模块化、Vue-cli脚手架搭建、开发、发布项目与综合示例
使用vue-cli可以规范项目,提高开发效率,但是使用vue-cli时需要一些ECMAScript6的知识,特别是ES6中的模块管理内容,本章先介绍ES6中的基础与模块化的内容再使用vue-cli开发 ...
- 听闰土大话前端之ES6是怎么来的
前言 相信做前端的朋友没有不知道ECMAScript6的,都知晓ES6新增了不少新的特性,但是你知道ES6是怎么来的吗?今天就让闰土来带大家大话ES6的前世今生.当然了,这篇文章会以扫盲为主,科普为辅 ...
- 120分钟React快速扫盲教程
在教程开端先说些题外话,我喜欢在学习一门新技术或读过一本书后,写一篇教程或总结,既能帮助消化,也能加深印象和发现自己未注意的细节,写的过程其实仍然是一个学习的过程.有个记录的话,在未来需要用到相关知识 ...
- 常用的ES6语法
1. let.const 和 block 作用域 let 允许创建块级作用域,ES6 推荐在函数中使用 let 定义变量,而非 var: var a = 2; { let a = 3; console ...
- ES6深入浅出_汇总贴
H:\BaiDu\ES6深入浅出-wjw ES 6 新特性一览:https://frankfang.github.io/es-6-tutorials/ 我用了两个月的时间才理解 let https:/ ...
- JavaScript学习总结(七)——ECMAScript6(ES6)
一.ECMAScript概要 ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers Association)通 ...
随机推荐
- Zabbix监控nginx-rtmp status(json版)
与前面的文章 zabbix监控nginx-rtmp status(html版)区别只在于取值的页面不一样 http://127.0.0.1:81/control/get/all_streams sta ...
- 【转载】STL之priority_queue
参考资料:传送门先回顾队列的定义:队列(queue)维护了一组对象,进入队列的对象被放置在尾部,下一个被取出的元素则取自队列的首部.priority_queue特别之处在于,允许用户为队列中存储的元素 ...
- linux下从SVN checkout目录源码下来
需求:我们替换http请求为https协议,要查看全不全,得到源码中去检查,所以自动化扫源码查询.但是得先有源码包啊.源码包直接从SVN上checkout 1.下载 [root@v50 0.02 sr ...
- centos6.5 卸载php
1.删除php,删除之前需要查看php依赖包,使用 rpm -qa|grep php [root@localhost ~]# rpm -qa |grep phpphp55w-mysql-5.5.38- ...
- Python Day12
MySQL 数据库介绍 什么是数据库? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库, 每个数据库都有一个或多个不同的API用于创建,访问,管理,搜索和复制所保存的数据. 我们 ...
- 【原创】JEECMS v6~v7任意文件上传漏洞(2)
文章作者:rebeyond 受影响版本:v6~v7 漏洞说明: JEECMS是国内Java版开源网站内容管理系统(java cms.jsp cms)的简称.该系统基于java技术开发,继承其强大.稳定 ...
- UML大战需求与分析--阅读笔记4
今天阅读了UML大战需求与分析第五.六章. 第五章,状态机图(State Machine Diagram),状态机图是通过描述某事物状态的改变来展现流程的.一般适用于流程围绕某个事物展开,例如请假的流 ...
- MyBatis Cache配置
@(MyBatis)[Cache] MyBatis Cache配置 MyBatis提供了一级缓存和二级缓存 配置 全局配置 配置 说明 默认值 可选值 cacheEnabled 全局缓存的开关 tru ...
- 异常详细信息: System.ComponentModel.Win32Exception: 拒绝访问。
本地win7 本地正常,服务器win2008r2,服务器报错! 异常详细信息: System.ComponentModel.Win32Exception: 拒绝访问. 拒绝访问. 说明: 执行当前 W ...
- ASP.MVC 基于AuthorizeAttribute权限设计案例
ASP.MVC上实现权限控制的方法很多,比如使用AuthorizeAttribute这个特性 1.创建自定义特性用于权限验证 public class AuthorizeDiy : Authorize ...