ES6简介
- ES的全程是EMCAScript,它是由EMCA国际标准化组织,指定的一项脚本语言标准化规范
- ES6就是JavaScript的一个发行版本, 于2015.06发行, 全称为ECMAScript. 一般来说JS我们刚开始学习的基础版本为ES5, ES6再ES5的基础上新增了一些新特性.
- ES6在ES5的基础上对其进行了升级, 解决了ES5的一些不足. 比如新增了类的概念.
- ES6在企业中应用很普遍.
新增声明方法
let
- let的新增是为了解决es5中使用var声明变量时存在的各种问题。
使用var的问题:
// 1. 使用var时,会存在声明提升的问题
console.log(test);
var test = 'test';
// 这里会把声明部分进行提升,将会输出test
// 2. 变量覆盖问题
var test = 'test1';
var test = 'test2';
console.log(test);
// 此处重复声明test变量,将会替换掉test变量的值
// 3. 块级作用域的问题
for (true){
var test = 'test';
}
for (var i = 0; i < 2; i++){
}
console.log(test); // test
console.log(i); // 2
let对上述问题的改正:
// 1. 不会声明提升
console.log(test);
let test = 'test';
// 这里会报错,不会提前声明
// 2. 不可重复声明
let test = 'test1';
let test = 'test2';
console.log(test);
// 此处报错,不能重复声明已经存在的变量
// 3. 修复块级作用域,let声明只在所在的作用域有效
for (true){
let test = 'test';
}
for (let i = 0; i < 2; i++){
}
console.log(test);
console.log(i);
// 此时输出将会输出test is not defined
// 4. 使用let声明的变量由暂时性死区的特性
// ES6 规定,如果区块中存在 let 和 const 命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”,也就是说使用let声明的变量都是先声明再使用 ,不存在变量提升问题。
var num = 10;
if (true) {
console.log(num);
let num;
}
// 报错原因:在块作用域内,let声明的变量被提升,但变量只是创建被提升,初始化并没有被提升(初始化就是给变量先赋值成undefined),在初始化之前使用变量,就会形成一个暂时性死区。
for循环计数器适合用let:
for (var i = 0; i < 10; i++) {
setTimeout(function(){
console.log(i);
})
}
// 输出十个 10
for (let j = 0; j < 10; j++) {
setTimeout(function(){
console.log(j);
})
}
// 输出 0123456789
/*
变量 i 是用 var 声明的,在全局范围内有效,所以全局中只有一个变量 i, 每次循环时,setTimeout 定时器里面的 i 指的是全局变量 i ,而循环里的十个 setTimeout 是在循环结束后才执行,所以此时的 i 都是 10。
变量 j 是用 let 声明的,当前的 j 只在本轮循环中有效,每次循环的 j 其实都是一个新的变量,所以 setTimeout 定时器里面的 j 其实是不同的变量,即最后输出 12345。(若每次循环的变量 j 都是重新声明的,如何知道前一个循环的值?这是因为 JavaScript 引擎内部会记住前一个循环的值)。
*/
面试题:
var arr = [];
for (var i = 0; i < 2; i++) {
arr[i] = function () {
console.log(i);
}
}
arr[0](); //2
arr[1](); //2
// 由于var声明的i并没有自己的块级作用域,所以等for循环结束之后,函数中的console.log(i)实际上调用的是循环之后的i值2
let arr = [];
for (let i = 0; i < 2; i++) {
arr[i] = function () {
console.log(i);
}
}
arr[0](); //0
arr[1](); //1
// 由于let声明的i存在自己的块级作用域,所以本质想循环中的i不会公用,会分别在自己的块级空间中存在一个i,当调用了函数时,函数会首先从自己的块级作用域中向上进行查找i,所以输出的时自己所在的块级作用域中的i的值
const
- 新增const用来声明常量,一旦声明,常量的值就不可改变。
- 通常来讲常量名使用大写。
- 一旦对变量进行声明就必须初始化。
- 和let一样,也具有块级作用域
const SUM = 30;
const TEST; // 没有进行初始化将会报错
const SUM = 40; // 可以重新声明来改变值
- const不可更改常量的本质时,被const声明之后的内存地址不允许改变
const arr = [100, 200];
arr[0] = 'a'; //此操作不会改变arr的内存地址
arr[1] = 'b'; //此操作不会改变arr的内存地址
arr = ['a', 'b']; //此操作会改变arr的内存地址,因此不被允许
- 所以对于基本数据类型不可更改,对于复杂数据类型数据本身不能更改,但是数据内部的值可以更改。
解构赋值
ES6中允许从数组中提取值,按照对应位置,对变量赋值。对象也可以实现解构。
数组解构
- 数组解构允许我们按照一一对应的关系从数组中提取值,然后赋值给变量
- 如果解构不成功,那么变量的值位undefined
let [a, b, c] = [1, 2, 3];
console.log(a);
console.log(b);
console.log(c);
对象解构
- 对象解构允许我们使用变量的名字匹配对象的属性,匹配成功将对象属性的值赋值给变量
let person = {name: 'borkyz', age: 20, sex: '男'};
let {name, sex} = person;
let {age} = person;
console.log(name);
console.log(sex);
console.log(age);
- 对象解构还允许我们将提取出来的值赋值给另外的变量
let person = {name: 'borkyz', age: 20, sex: '男'};
let {name: myName, sex: mySex} = person;
console.log(myName);
console.log(mySex);
箭头函数
- 箭头函数是用来简化函数定义语法的。
- 如果传入参数只有一个那么小括号可以省略/
- 在箭头函数中,如果函数体中只有一句代码,并且代码执行结果就是函数的返回值,函数体大括号就可以省略。
(arg1, arg2, ...) => {code}
let sum = (a, b) => {
console.log(a);
console.log(b);
console.log(a+b);
return a+b;
}
// 传入参数是一个那么可以省略小括号
let put = a => {
console.log(a);
}
// 一行代码并且返回执行结果就可以省略大括号
let plus = (a, b) => a + b;
箭头函数的this指向
箭头函数不绑定this,因此箭头函数没有自己的this关键字,如果在箭头函数中调用this,那么this应该指向箭头函数定义位置中的this。
function fn () {
console.log(this);
return () => {
console.log(this);
}
}
const obj = {name: 'brokyz'};
const resFn = fn.call(obj);
// 输出结果
面试题
var obj = {
age: 20,
say: () => {
alert(this.age);
}
}
obj.say(); // undefined
// 箭头函数定义在了obj对象中,由于obj是对象,所以obj没有产生作用域,所以这个箭头函数实际上是被定义在了全局作用域下。因此this指向window,window中没有age所以弹出了undefined
剩余参数
- 剩余参数语法允许我们将一个不定数量的参数表示为一个数组。
arguments
将会以伪数组的形式存储我们传入函数的所有参数。- 在箭头函数中无法使用
arguments
。
function fn(first, ...args) {
console.log(first); // 10
console.log(args); // [20, 3]
console.log(arguments); // [10, 20, 30]伪数组
}
fn(10, 20, 30);
// 箭头函数中无法使用 arguments
const sum = (...args) => {
let total = 0;
args.forEach(item => total += item);
return total;
};
console.log(sum(10, 20, 30)); // 60
剩余参数和解构配合使用
let student = ['wangwu', 'zhangsan', 'lisi'];
let [st1, ...st2] = student;
console.log(st1); // wangwu
console.log(st2); // ['zhangsan', 'lisi']
ES6内置的对象扩展
Array 的扩展方法
扩展运算符(展开语法)
扩展运算符可以将数组或者对象转为用逗号分隔的参数序列。
let arr = [1, 2, 3];
console.log(...arr); // 1 2 3
// 注意:...arr实际上值是1, 2, 3带有逗号,但是输出时,被当作参数了
console.log(1, 2, 3); // 1 2 3
应用:合并数组
// 方法1
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let arr3 = [...arr1, ...arr2];
console.log(arr3); // [1, 2, 3, 4, 5, 6]
// 方法2
let arr4 = arr1.push(...arr2);
应用:将伪数组转换为真正的数组
let lis = document.querySelectorAll('li');
arrLis = [...lis];
console.log(lis); // NodeList(4) [li, li, li, li]
console.log(arrLis); // (4) [li, li, li, li]
// 测试数组的方法
arrLis.push('a'); // 未报错
console.log(arrLis); // (5) [li, li, li, li, 'a']
构造函数方法:Array.from()
Array.from()
方法可以将类数组或者可遍历的对象转换为真正的数组。Array.from()
可以接受第二个函数参数来对数组进行加工。
// 模仿伪数组
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
'length': 3
}
let arr = Array.from(arrayLike); // ['a', 'b', 'c']
console.log(arr);
// 可以传入函数对数组进行加工
let arrayLike2 = {
'0': 1,
'1': 2,
'2': 3,
'length': 3
}
let arr2 = Array.from(arrayLike2, item => item * 2); // [1, 4, 6]
console.log(arr2);
实例方法:find()
- 用于查找第一个符合条件的数组成员,如果没有找到返回 undefined。
let arr = [{
id: 1,
name: '张三'
}, {
id: 2,
name: '李四'
}];
let target = arr.find((item, index) => item.id == 2);
console.log(target); // {id: 2, name: '李四'}
实例方法:findIndex()
- 用于找出第一个符合条件的数组成员的位置,如果没有找到返回-1。
let arr = [1, 5, 10, 15];
let index = arr.findIndex((vlaue, index) => vlaue > 9);
console.log(index); // 2
实例方法:includes()
- 表示某个数组是否包含给定的值,返回布尔值。
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
String 的扩展方法
模板字符串
- 模板字符串可以解析变量。
- 模板字符串可以换行。
- 模板字符串可以调用函数。
let name = 'brokyz';
let sayHello = `hello, my name is ${name}`; // hello, my name is brokyz
// 模板字符串可以换行
let sayHi = () => 'Hi!';
let html = `
<div>
<span>${sayHi()}</span>
</div>
`;
console.log(html);
实例方法:startsWith() 和 endsWith()
startsWith()
表示参数字符串是否在原字符产的头部,返回布尔值。endsWith()
表示参数字符串是否在原字符串的尾部,返回布尔值。
let str = 'Hello world!';
str.startsWith('Hello') // true
str.startsWith('!') // true
实例方法:repeat()
repeat()
方法表示将原字符串重复n次,返回一个新字符串。
'x'.repeat(3) // 'xxx'
'hello'.repeat(2) // 'hellohello'
Set 数据结构
- ES6 提供了新的数据解构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
- Set本身是一个构造函数,用来生成Set数据解构。
const s = new Set();
- Set 函数可以接受一个数组作为参数,用来初始化。
const set = new Set([1, 2, 3, 4, 4]);
console.log(set); // Set(4) {1, 2, 3, 4}
console.log(set.size)
数组去重
const set = new Set([1, 2, 3, 4, 4]);
const arr = [...set];
console.log(arr); // [1, 2, 3, 4]
实例方法
add(value)
:添加某个值,返回 Set 解构本身。delete(value)
:删除某个值,返回一个布尔值,表示删除成功。- has(value):返回一个布尔值,表示该值是否为 Set 成员。
clear()
:清除所有成员,没有返回值。
const set = new Set();
s.add(1).add(2).add(3); // 向set结构中添加值
s.delete(2); // 删除set结构中的2值
s.has(1); // 表示set结构中是否有1这个值,返回布尔值
s.clear() // 清除所有成员,没有返回值
遍历
- Set 结构的实例与数组一样,也拥有 forEach 方法,用于对每个成员执行某种操作,没有返回值。
s.forEach(value => console.log(value));
const set = new Set(['a', 'b', 'c']);
set.forEach(value => {
console.log(value);
})
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/279113.html