BCSP-玄子前端开发之JavaScript+jQuery入门CH08_ECMAScript 6进阶
4.8 字符串的扩展
模板字符串
- 使用反引号 ()代替普通字符串中的双引号和单引号
- 可当作普通字符串使用,也可用来定义多行字符串
//多行字符串
document.write(`
最快的脚步不是跨越,而是继续;<br>
最慢的步伐不是缓慢,而是徘徊;<br>
最好的道路不是大道,而是坦荡;<br><hr> `);
//字符串中嵌入变量
let name = "Bob", time = "today";
document.write(`Hello ${name}, how are you ${time}?`);
4.8.1 字符串新增方法
方法 | 局部变量 |
---|---|
includes(searchString:string):boolean | 返回布尔值,表示是否找到了参数字符串 |
startsWith(searchString:string):boolean | 返回布尔值,表示参数字符串是否在原字符串头部 |
endsWith(searchString:string):boolean | 返回布尔值,表示参数字符串是否在原字符串尾部 |
repeat(count:number):string | 返回一个新字符串,表示将原字符串重复n次 |
padStart(length:number,string:string):string | 用于头部补全 |
padEnd(length:number,string:string):string | 用于尾部补全 |
trimStart():string | 消除字符串头部的空格 |
trimEnd():string | 消除尾部的空格 |
4.9 数组的扩展
- 扩展运算符
- Array.from()
- 数组的新增方法
- entries()
- keys()
- values()
4.9.1 扩展运算符
三个点(…),可将一个数组转为用逗号分隔的序列
let arr = [];
//扩展运算符的基本用法
arr.push(...[1,2,3,4,5]);
console.log(arr); //[1,2,3,4,5]
console.log(1, ...[2, 3, 4], 5) //1 2 3 4 5
//可以放置表达式
console.log(...(1 > 0 ? ['a'] : [])); //a
//空数组,不产生效果
console.log([...[], 1]); //[1]
//用于函数调用
function push(array, ...items) { array.push(...items);}
function add(x, y) { console.log(x + y);}
const numbers = [4, 38];
add(...numbers) // 42
4.9.2 扩展运算符-替代函数的apply方法
通过push函数,将一个数组添加到另一个数组的尾部
// ES5的 写法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
Array.prototype.push.apply(arr1, arr2);
// ES6 的写法
let arr3 = [0, 1, 2];
let arr4 = [3, 4, 5];
arr3.push(...arr4);
4.9.3 扩展运算符-应用
- 复制数组
- 合并数组
- 与解构赋值结合
- 将字符串转为真正的数组
//复制数组
// ES5 的写法
const a1 = [1, 2];
const a2 = a1.concat();
console.log(a2);
// ES6 的写法
const a1 = [1, 2];
const a2 = [...a1];
console.log(a2);
//或
const [...a2] = a1;
console.log(a2);
//合并数组
const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];
// ES5 的合并数组
console.log(arr1.concat( arr2, arr3));
// ES6 的合并数组
console.log([...arr1, ...arr2, ...arr3]);
//与解构赋值结合使用
const [first, ...rest] = [1, 2, 3, 4, 5];
console.log(first);
console.log(rest);
//扩展运算符位置
const [...butLast, last] = [1, 2, 3, 4, 5]; // 报错
const [first, ...middle, last] = [1, 2, 3, 4, 5]; // 报错
4.9.4 Array.from()
- 用于将类数组对象或者可遍历对象转换成一个真正的数组
- 类数组对象,最基本的要求是具有length属性的对象
let arrayLike = {
0: 'tom',
1: '65',
2: '男',
3: ['jane','john','Mary'],
'length': 4}
let arr = Array.from(arrayLike)
console.log(arr)
//['tom','65','男',['jane','john','Mary']]
let arrayLike = {
'name': 'tom',
'age': '65',
'sex': '男',
'friends': ['jane','john','Mary'],
length: 4 }
let arr = Array.from(arrayLike)
console.log(arr)
//[undefined, undefined, undefined, undefined]
4.9.5 类数组对象转换为真正的数组
- 类数组对象必须具有length属性,用于指定数组的长度
- 如果没有length属性,那么转换后的数组是一个空数组
- 类数组对象的属性必须为数值型或字符串型的数字
4.9.6 遍历数组
- keys():对键名的遍历
- values():对键值的遍历
- entries():对键值对的遍历
for (let index of ['张三', '李四'].keys()) {
console.log(index); }
for (let elem of ['张三', '李四'].values()) {
console.log(elem); }
for (let [index, elem] of ['张三', '李四'].entries()) {
console.log(index, elem); }
4.10 对象的扩展
数据结构本身的改变
- 属性的简洁表示法
- 属性名表达式
对象的新增方法
- Object.is()
- Object.assign()
对象遍历
4.10.1 属性的简洁表示法
ES6允许在对象之中,直接写变量
const foo = 'bar';
const baz = {foo};
// 等同于
const baz = {foo: foo};
//除了属性简写,方法也可以简写
const o = {
method() { return "Hello!";}
};
// 等同于
const o = {
method: function() { return "Hello!";}
};
let name = '小明';
let birth = '2001/12/23';
//普通写法
const Person = {
name: name,
birth: birth,
getInfo: function () {
console.log(`我的名字是:${this.name},我出生时间是:${this.birth}`);
}};
Person.getInfo();
//简洁写法
const Person = {
name,
birth,
getInfo () {
console.log(`我的名字是:${this.name},我出生时间是:${this.birth}`);
}};
Person.getInfo();
4.10.2 属性名表达式
//JavaScript 定义对象的属性
// 方法1:用标识符作为属性名
obj.foo = true;
// 方法2:表达式作为属性名
obj['a' + 'bc'] = 123;
//使用字面量方式定义对象,只能使用标识符定义属性
var obj = {
foo: true,
abc: 123
};
//使用字面量方式定义对象时,ES6允许用表达式作为属性名
let propKey = 'foo';
let obj = {
[propKey]: true,
['a' + 'bc']: 123
};
//表达式还可以用于定义方法名
let obj = {
['h' + 'ello']() { return 'hi';}
};
obj.hello()
4.10.3 Object.is()
用来比较两个值是否严格相等,与严格比较运算符(===
)的行为基本一致
ES5中用来比较两个值是否相等的运算符
- 比较运算符(
==
) - 严格比较运算符(
===
)
两个不同之处
- +0不等于-0
- NaN等于自身
4.10.4 Object.assign()
用于对象的合并,将源对象的所有可枚举属性,复制到目标对象
Object.assign(target, source1, source2);
// source1 源对象
// target 目标对象
//基本用法
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);
console.log(target); // {a:1, b:2, c:3}
//如果目标对象与源对象有同名属性,或多个源对象有同名属性
const target1 = { a: 1, b: 1 };
const source3 = { b: 2, c: 2 };
const source4 = { c: 3 };
Object.assign(target1, source3, source4);
console.log(target1); // {a:1, b:2, c:3}
//如果只有一个参数
const obj = {a: 1};
Object.assign(obj) === obj // true
//如果非对象参数出现在源对象的位置
let obj = {a: 1};
Object.assign(obj, undefined) === obj // true
Object.assign(obj, null) === obj // true
//其他类型的值不在首参数
const v1 = 'abc';const v2 = true;const v3 = 10;
const obj = Object.assign({}, v1, v2, v3);
4.10.5 Object.assign()
常见用途
- 为对象添加属性
- 为对象添加方法
- 克隆对象
- 合并多个对象
- 为属性指定默认值
4.10.6 对象遍历
Object.keys()
- 返回成员是参数对象自身的所有可遍历属性的键名
Object.values()
- 返回成员是参数对象自身的所有可遍历属性的键值
Object.entries()
- 返回成员是参数对象自身的所有可遍历属性的键值对数组
var obj = { foo: 'bar', baz: 42 };
console.log(Object.keys(obj));// ["foo", "baz"]
console.log(Object.values(obj));// ["bar", 42]
//如果属性名为数值的属性
const obj1 = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.values(obj1))// ["b", "c", "a"]
//如果Object.values方法的参数是一个字符串
console.log(Object.values('foo'));// ["f", "o", "o"]
//如果Object.values方法的参数是数值和布尔值
console.log(Object.values(42)) // []
console.log(Object.values(true)) // []
console.log(Object.entries(obj))// [ ["foo", "bar"], ["baz", 42]
4.11 set和Map对象
4.11.1 Set数据结构-基本用法
set数据结构类似于数组,但成员的值都是唯一的,没有重复的值
//例1:单一数组的去重
let set1 = new Set([1, 2, 2, 3, 4, 3, 5])
console.log(set1);
//例2:多数组的合并去重
let arr1 = [1, 2, 3];
let arr2 = [2, 3, 4, 5];
let set2 = new Set([...arr1, ...arr2])
console.log(set2);
//例3:字符串去重
console.log([...new Set('ababbc')].join(''));
//例4:Set函数接受数组作为参数
const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
console.log(items.size); // 5
4.11.2 Set数据结构-属性和方法
分类 | 属性**/**方法 | 描述 |
---|---|---|
属性 | Set.prototype.constructor | 构造函数,默认就是Set函数 |
Set.prototype.size | 返回Set实例的成员总数 | |
操作方法 | Set.prototype.add(value) | 添加某个值,返回 Set 结构本身 |
Set.prototype.delete(value) | 删除某个值,返回一个布尔值,表示删除是否成功 | |
Set.prototype.has(value) | 返回一个布尔值,表示该值是否为Set的成员 | |
Set.prototype.clear() | 清除所有成员,没有返回值 | |
遍历方法 | Set.prototype.keys() | 返回键名的遍历器 |
Set.prototype.values() | 返回键值的遍历器 | |
Set.prototype.entries() | 返回键值对的遍历器 | |
Set.prototype.forEach() | 使用回调函数遍历每个成员 |
let set1 = new Set();
//向Set中添加元素
set1.add(1);
set1.add(2);
set1.add(3);
console.log(set1);//{1, 2, 3}
//返回Set实例的成员总数
console.log(set1.size);//3
//从Set中删除元素
set1.delete(1);
console.log(set1);//{2, 3}
//判断某元素是否存在
console.log(set1.has(1));//false
console.log(set1.has(2));//true
//清除所有元素
set1.clear();
console.log(set1);//{};
//Set转数组
let set2 = new Set([4, 5, 6]);
console.log(Array.from(set2)); //[4, 5, 6]
4.11.3 Set数据结构-遍历方法
let set = new Set(['red', 'green', 'blue']);
for (let item of set.keys()) {
console.log(item);
}
for (let item of set.values()) {
console.log(item);
}
for (let item of set.entries()) {
console.log(item);
}
Map数据结构-概念
JavaScript中的对象本质上是键值对的集合,但是传统上只能用字符串当作键
Map数据结构类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值都可以当作键
Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应
4.11.4 Map数据结构-基本用法
//Map构造函数接受数组作为参数
const map = new Map([['name', '张三'],['title', 'Author']]);
console.log(map.get('name')) // "张三"
console.log(map.get('title')) // "Author"
//Set和Map都可以用来生成新的 Map
const set = new Set([['foo', 1],['bar', 2]]);
const m1 = new Map(set);
console.log(m1.get('foo')) // 1
const m2 = new Map([['baz', 3]]);
const m3 = new Map(m2);
console.log(m3.get('baz')) // 3
//如果对同一个键多次赋值
const map1 = new Map();
map1.set(1, 'aaa');
map1.set(1, 'bbb');
console.log(map1.get(1)) // "bbb"
//如果读取一个未知的键
console.log(new Map().get('asfddfs'));// undefined
//只有对同一个对象的引用,Map 结构才将其视为同一个键
const map2 = new Map();
map2.set(['a'], 555);
console.log(map2.get(['a'])) // undefined
4.11.5 Map数据结构-属性和方法
分类 | 属性**/**方法 | 描述 |
---|---|---|
属性 | size 属性 | 返回 Map 结构的成员总数 |
操作方法 | Map.prototype.set(key, value) | 设置键名key对应的键值为value,返回整个 Map 结构 |
Map.prototype.get(key) | 读取key对应的键值,如果找不到key,返回undefined | |
Map.prototype.has(key) | 返回一个布尔值,表示某个键是否在当前 Map 对象之中 | |
Map.prototype.delete(key) | 删除某个键,返回true。如果删除失败,返回false | |
Map.prototype.clear() | 清除所有成员,没有返回值 | |
遍历方法 | Map.prototype.keys() | 返回键名的遍历器 |
Map.prototype.values() | 返回键值的遍历器 | |
Map.prototype.entries() | 返回所有成员的遍历器 | |
Map.prototype.forEach() | 遍历 Map 的所有成员 |
//size属性
const map1 = new Map();
map1.set('foo', true);
map1.set('bar', false);
map1.size;
//set方法
const map2 = new Map();
map2.size;
map2.set('edition', 6);
map2.set(262, 'standard');
map2.set(undefined, 'nah');
map2.size;
//get方法
const map3 = new Map();
const hello = function() {
console.log('hello');
};
map3.set(hello, 'Hello ES6!');
map3.get(hello));
//has方法
map2.has('edition');
map2.has('years');
map2.has(2);
map2.has(undefined);
4.11.6 Map数据结构-遍历方法
const map = new Map([
['F', 'no'],
['T', 'yes'],
]);
for (let key of map.keys()) {
console.log(key);
}
for (let value of map.values()) {
console.log(value);
}
for (let item of map.entries()) {
console.log(item[0], item[1]);
}
map.forEach(function(value, key, map) {
console.log( key, value);
});
4.12 Module的语法-概述
JavaScript一直没有模块体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来
ES6模块带来的好处
- 避免变量污染
- 命名冲突
- 提高代码复用
- 率提高维护性
- 依赖关系的管理
4.12.1 Module的语法-命令
模块功能主要由两个命令构成
- export命令:用于规定模块的对外接口
- import命令:用于输入其他模块提供的功能
4.12.2 export命令
使用export命令可以做到外部能够读取模块内部的某个变量
// profile.js
//写法一
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
//写法二
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export { firstName, lastName, year };
//输出函数或类
export function multiply(x, y) {
return x * y;};
//使用as关键字重命名
function v1() { ... }
function v2() { ... }
export {
v1 as streamV1,
v2 as streamV2,
v2 as streamLatestVersion
};
4.12.3 import命令
import命令用于输入其他模块提供的功能
// main.js
//1、基本使用
import { firstName, lastName, year } from './profile.js';
function setName(element) {
element.textContent = firstName + ' ' + lastName;}
//2、使用as关键字,将输入的变量重命名
import { lastName as surname } from './profile.js';
//3、不允许在加载模块的脚本里面,改写接口
import {a} from './xxx.js'
a = {}; // Syntax Error : 'a' is read-only;
a.foo = 'hello'; // 合法操作,因为改写a的属性是允许的
4.12.4 模块的整体加载
用星号(*)指定一个对象,所有输出值都加载在这个对象上面
// circle.js
export function area(radius) {
return Math.PI * radius * radius;
}
export function circumference(radius) {
return 2 * Math.PI * radius;
}
//main.js 加载模块(逐一加载)import { area, circumference } from './circle';
console.log('圆面积:' + area(4));
console.log('圆周长:' + circumference(14));
//main.js 加载模块(整体加载)
import * as circle from './circle';
console.log('圆面积:' + circle.area(4));
console.log('圆周长:' + circle.circumference(14));
4.12.5 export default命令
export default命令为模块指定默认输出
//1、基本用法
// export-default.js
export default function () {
console.log('foo');
}
// import-default.js
import customName from './export-default';
customName(); // 'foo'
//2、比较默认输出和正常输出
// 第一组
export default function crc32() { // 输出
// ...
}
import crc32 from 'crc32'; // 输入
// 第二组
export function crc32() { // 输出
// ...
};
import {crc32} from 'crc32'; // 输入
BCSP-玄子前端开发之JavaScript+jQuery入门CH08_ECMAScript 6进阶