es6 新增数据类型_前端·ES6基础

10b0268f4bce9ec058c277d70e9236b8.png

知识点1:ECMAScript6与ECMAScript2015

ES6是JavaScript在ES5之后的下一代标准,于2015年6月正式发布,旨在使js能编写复杂大型应用程序,成为企业级开发语言。

ES6标准的开发过程中,决定在每年6月份正式发布一次作为当年的正式版本,其他时间则在这个版本基础上改动,因此版本号就不再需要,只要用年份标记即可。所以,ES6泛指ES5.1版后的JavaScript下一代标准,涵盖了ES2015、ES2016、ES2017等。

使用Babel、Traceur等转码器能将ES6代码转为ES5代码。

知识点2:let与const

ES6新增的变量声明关键字,let声明的变量只在其所在代码块内有效,实现了“块级作用域”的效果;const声明一个只读的常量,一旦声明就不能改变值(因此一旦声明必须立即初始化)。

const同样只在块级作用域内有效。但本质上const是让变量指向的那个内存地址保存的数据不得改动,对于对象和数组,变量指向的内存地址保存的只是一个指向实际数据的指针,const只能保证这个指针固定,对象或数组本身是可变的。

let与const不存在变量提升。在一个区块中如果存在let和const,这个区块对声明的变量从一开始就会形成封闭作用域,如果在声明前使用这些变量就会报错,这称为“暂时性死区TDZ”。

从ES6开始,全局变量将逐步与顶层对象的属性脱钩,因此let、const声明的全局变量不属于顶层对象的属性。

知识点3:变量的解构赋值

ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。解构的本质类似于“模式匹配”,解构不成功则值等于undefined。例:

let [a, b, c] = [1, 2, 3];

类似于“模式匹配”:

let [foo, [[bar], baz]] = [1, [[2], 3]];

而对象解构要求变量与属性同名,例:

let { foo, bar } = { foo: 'aaa', bar: 'bbb' };

如果变量名与属性名不一致,则应写成:

let { foo: baz } = { foo: 'aaa' }; // foo是模式,baz才是变量

解构赋值还允许指定默认值,例:

let [x, y = 'b'] = ['a'];

字符串也可以解构赋值,此时字符串被转换成了一个类似数组的对象。例:

const [a, b, c, d, e] = 'hello';

可以利用变量的解构赋值交换变量的值。例:

[x, y] = [y, x];

知识点4:字符串的扩展

1.模板字符串是增强版的字符串,用反引号`标识。既可当作普通字符串,又可在字符串中嵌入变量(将变量名、表达式甚至函数调用写在${}中)。例:

let name = "Bob", time = "today";

`Hello ${name}, how are you ${time}?`

模板字符串可以紧跟在一个函数名后面,该函数将被调用来处理这个模板字符串,这被称为“标签模板”功能。

2.新增方法:

String.fromCodePoint()。用于从Unicode码点返回对应字符,可识别大于0xFFFF的字符(js中字符以UTF-16存储每个字符固定为2字节,因此对于那些Unicode码点大于0xFFFF的字符,js会认为它们是两个字符)。如有多个参数会被合并成一个字符串返回;

3.新增实例方法:

codePointAt(),参数是字符在字符串中的位置,可识别大于0xFFFF的字符会正确返回32位的码点(2字节存储的常规字符其返回结果与charCodeAt()相同);

includes(),返回布尔值,表示是否找到了参数字符串;

startsWith()、endsWith(),返回布尔值,表示参数字符串是否在原字符串的头/尾部;

repeat(),返回一个新字符串,表示将原字符串重复n次;

trimStart()、trimEnd(),其行为与trim()一致,只是分别用来消除头部和尾部的空格,均返回新字符串;

知识点5:数值的扩展

1.二进制和八进制数值有了新的写法,分别用前缀0b和0o表示;

2.新增方法:

Number.isFinite()、Number.isNaN(),用来检查一个数值是否有限与是否为NaN。它们与传统的全局方法isFinite()和isNaN()的区别在于,这两个方法只对数值有效;

Number.parseInt()、Number.parseFloat(),将这两个全局方法移植到Number对象上,为了逐步减少全局性方法,使语言逐步模块化;

Number.isInteger(),用于判断一个数值是否为整数。对数据精度要求高不建议使用;

3.Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER,js有一个能准确表示的整数范围,超过范围则无法精确表示这个值。这两个常量来表示这个范围的上下限。Number.isSafeInteger()则用来判断一个整数是否落在这个范围内;

4.新增指数运算符 **;

知识点6:函数的扩展

1.新增箭头函数,允许使用=>定义函数。例:

var sum = (num1, num2) => num1 + num2;// 等同于var sum = function(num1, num2) {return num1 + num2;};

如果函数代码块部分多于一条语句,就要用大括号括起来并用retrun返回。

箭头函数没有自己的this,内部的this就是外层代码块的this,因此其指向会固定化,就是定义时所在对象;

2.允许为函数参数设置默认值,例:

function log(x, y = 'World') {console.log(x, y);}。

3.引入rest参数(形式为...变量名),用于获取函数的多余参数并放入一个数组中;

4.name属性返回函数的函数名;

5.尾调用优化。尾调用是函数式编程的一个重要概念,指某个函数的最后一步是调用另一个函数。尾调用优化会只保留内层函数的调用帧,因此如果使用“尾递归”,就不会发生栈溢出。尾调用优化只在严格模式下开启;

知识点7:数组的扩展

1.扩展运算符...。它好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列。例:

Math.max(...[14, 3, 77]); //直接数组无法使用max

const a2 = [...a1]; //复制一个数组

[...'hello'] //将字符串转为真正的数组

2.新增方法:

Array.from()用于将“类似数组的对象”和“可遍历的对象”转为真正的数组;

Array.of()用于将一组值转换为数组,无参数则返回空数组,例:Array.of(3, 11, 8);

3.新增实例方法:

find()、findIndex()找出第一个符合条件的数组成员,分别返回该成员与成员位置。其参数是一个回调函数,直到找出第一个返回值为true的成员。例:[1, 4, -5, 10].find((n) => n < 0);

fill()使用给定值填充一个数组,第二第三参数指定填充的起始结束位置;

include()返回某个数组是否包含给定的值;

flat()该方法返回一个新数组,将数组中的子数组成员取出来添加在原来的位置,“拉平”变成一维的数组。方法默认只会“拉平”一层,如果想对多层的嵌套数组使用可以传入一个整数表示想拉平的层数;

知识点8:对象的扩展

1.ES6允许在对象中直接写变量和函数,这时属性/方法名为变量/函数名,属性值为变量/函数的值;

2.ES6允许用字面量定义对象时,把表达式放在方括号内,作为对象属性名;

3.super关键字指向当前对象的原型对象,该关键字只能用在对象的方法之中;

4.对象的扩展运算符...用于取出参数对象的所有可遍历属性,并拷贝到当前对象之中,例:

let z = { a: 3, b: 4 }; let n = { ...z }; //使得n为{ a: 3, b: 4 };

5.新增方法:

Object.assign()用于对象合并,将源对象的所有自身且可枚举属性复制到目标对象。其中第一个参数为目标对象,其他参数为源对象。该方法实行的是浅拷贝,另外当出现同名属性时后面的属性会覆盖前面的属性;

Object.setPrototypeOf()设置一个对象的prototype对象,参数为obj, proto;

Object.getPrototypeOf()读取一个对象的原型对象;

Object.values()返回一个数组,成员是参数对象自身的所有可遍历属性的键值;

Object.entries()返回一个数组,成员是参数对象自身的所有可遍历属性的键值对数组;

Object.fromEntries()是Object.entries()的逆操作,特别适合将map结构转为对象;

知识点9:Symbol

ES6引入了一种新的原始数据类型Symbol,表示独一无二的值,它是js语言的第七种数据类型。

Symbol通过Symbol函数生成,可接受一个字符串作为参数,该字符串只是作为对当前Symbol值的描述,因此相同参数的Symbol函数的返回值并不相等。例:

let s = Symbol('foo');

s.description //'foo'

Symbol主要作为对象属性名,以保证不会出现同名的属性,定义时需要放在方括号之中。例:

let mySymbol = Symbol();

let a = {[mySymbol]: 'Hello!'};

a[mySymbol] // "Hello!"

Symbol作为属性名,不会出现在for...in循环中,也不会被keys、getOwnpropertyNames()等方法返回。通过Object.getOwnPropertySymbols()可获取对象的所有Symbol值。

知识点10:Set与Map

ES6中新增Set与Map数据结构。Set中成员的值都是唯一的;Map提供了“值—值”的对应,是一种更完善的Hash结构实现。例:

const set = new Set();

const map = new Map();

Set的属性和方法有:size属性返回结构成员总数,add()添加某个值,delete()删除某个值,has()查找某值是否为其成员,clear()清除所有成员;

Map的属性和方法有:size、set(key, value)、get(key)、delete(key)、has(key)、clear()。

与数组一样Set和Map都有forEach()使用回调函数遍历每个成员,参数依次为键值、键名(set的键名就是键值),例:

mySet.forEach((value, key) => console.log(key + ' : ' + value));

另外,扩展运算符...也可以用于Set和Map,例:let arr = [...set];

知识点11:for...of循环

任何数据结构只要部署 Iterator 接口(Symbol.iterator属性),就可以被ES6中遍历命令for...of循环遍历。有些数据结构原生具备Iterator接口,如Array、Map、Set、String、arguments、NodeList等。例:

var es6 = new Map();

for (let [name, value] of es6) {

console.log(name + ": " + value);

}

知识点12:Class类

1.ES6引入了类的概念,使用class关键字可定义类。例:

class Point {

constructor(x, y) {

this.x = x;

this.y = y;

}

toString() {

return '(' + this.x + ', ' + this.y + ')';

}

}

定义类的方法时,前面不需要加function,方法之间也不需要逗号。事实上类的所有方法都是定义在类的prototype属性上面。

一个类必须有constructor方法,使用new生成对象实例会自动调用该方法。

2.实例属性除了定义在constructor()里面的this上面,也可以定义在类的最顶层。例:

class foo {

bar = 'hello';

baz = 'world';

constructor() {

// ...

}}

3.在类的内部可以使用get和set关键字,对某个属性设置存值函数和取值函数。例:

class MyClass {

constructor() {

// ...

}

get prop() {

return 'getter';

}

set prop(value) {

console.log('setter: '+value);

}}

inst.prop = 123;

4.类相当于实例的原型,所有在类中定义的方法都会被实例继承。使用static能使方法变成静态方法,只能通过类来调用。

而ES6中规定Class内部只有静态方法,没有静态属性,因此静态属性只能这样写,例:

class Foo {}

Foo.prop = 1;

5.通过extends关键字实现继承,例:

class ColorPoint extends Point {

constructor(x, y, color) {

super(x, y); // 调用父类的constructor(x, y)

this.color = color;

}

}

子类必须在constructor中调用super(),即父类的构造函数。因为子类自己的this对象必须先通过父类的构造函数完成塑造,如果不调用super子类就得不到this对象。这点ES6的继承和ES5的继承完全不同,ES5中是先创造子类的this,然后再将父类的方法添加到this上面。

知识点13:Promise

Promise是异步编程的一种解决方案,有了它就可以避免层层嵌套的回调函数。Promise是一个容器,通常保存着一个异步操作的结果。

1.生成Promise实例。例:

const promise = new Promise(function(resolve, reject) {

// ... some code

if (/* 异步操作成功 */){

resolve(value);

} else {

reject(error);

}});

其中resolve和reject是两个由js引擎提供的函数,分别用于将状态从“进行中”变为“成功”或“失败”,调用它们并不会终结Promise的参数函数的执行。

2.待实例生成后,用then分别指定两种状态的回调函数:

promise.then(function(value) {

// success

}, function(error) {

// failure

});

3.还可以用catch()指定发生错误时的回调函数,用finally()指定不管Promise对象最后状态如何都会执行的操作。例:

promise

.then(result => {···})

.catch(error => {···})

.finally(() => {···});

4.Promise.all()用于将多个Promise实例包装成一个新的Promise实例,多个请求会并发执行,只有每个状态都变成fulfilled(成功)才会变成fulfilled,只要有一个rejected(失败)则合起来状态变成rejected。例:

const p = Promise.all([p1, p2, p3]);

知识点14:async函数

ES2017引入async使得异步操作更加方便,async函数完全可以看作多个异步操作包装成的一个Promise 对象。async表示函数里有异步操作,await表示后面的表达式需要等待结果。例:

async function getStockPriceByName(name) {

const symbol = await getStockSymbol(name);

const stockPrice = await getStockPrice(symbol);

return stockPrice;

}

getStockPriceByName('goog').then(

function (result) {console.log(result);});

async函数返回一个Promise对象,因此可以使用then添加回调函数,async内部返回的值会成为then的参数。该Promise 对象必须等到内部所有await命令后面的Promise对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数。

函数执行时一旦遇到await就会先返回,等异步操作完成再接着执行函数体内后面的语句。如果多个异步操作不存在继发关系,最好用Promise.all()让它们同时触发,缩短程序执行时间。

任何一个await语句后面的Promise对象变为reject状态,整个async函数都会中断执行,因此可以将await放在try...catch里面。

知识点15:ES6模块

历史上js一直没有模块体系,对于开发大型复杂的项目形成了巨大障碍。社区制定了一些模块加载方案,主要有CommonJS和AMD两种。

ES6使用export命令与import实现了模块功能,完全可以取代上述两种规范。其设计思想是静态化,使得编译时就能确定模块的依赖关系,而之前的两种都是运行时加载。

1.export命令常见用法有:

export var year = 1958; //输出一个变量

export { firstName, lastName, year }; //输出一组变量

export function multiply(x, y) {}; //输出函数

export {n as m}; //重命名为m

export default function(){}; //export default为模块指定默认输出,只能使用一次

export * from 'circle'; //输出别的模块的所有属性和方法

2.import命令会提升到整个模块头部首先执行,from后指定的位置可以是相对路径或绝对路径,后缀可以省略,常见用法有:

import { stat, exists, readFile } from 'fs'; //大括号中变量名需与模块对外的接口名称一致

import { lastName as surname } from './profile.js'; //重命名

import * as circle from './circle'; //用星号指定一个对象所有输出值都加载在这个对象上面

import customName from './export-default'; //用任意名字(不使用大括号)指向默认输出而无需知道原模块输出的函数名

3.浏览器加载ES6使用type="module",会异步加载等到页面渲染完再执行模块脚本,等同于打开defer属性。例:

<script type="module" src="./foo.js"></script>

4.ES6模块与CommonJS模块完全不同,CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。另外,Node要求ES6模块采用.mjs后缀文件名,require不能加载只有import能加载。

知识点16:编码规范

(参考Airbnb公司:https://github.com/airbnb/javascript)

1.let取代var,let和const之间优先使用const,所有函数都应该设置为常量;

2.静态字符串一律使用单引号而不用双引号,动态字符串使用反引号;

3.使用数组成员对变量赋值时,或函数参数如果是对象的成员,优先使用解构赋值;

4.多行定义的对象最后一个成员以逗号结尾;

5.对象一旦定义不随意添加新属性,若添加则使用Object.assign();

6.对象的属性和方法尽量采用简洁表达式;

7.使用扩展运算符拷贝数组[...items];

8.使用Array.from()将类似数组的对象转为数组;

9.需要使用函数表达式的场合尽量用箭头函数代替;

10.不在函数体内使用arguments变量,使用rest运算符代替。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值