变量
在学习ES6之前,我们所熟悉的有且仅有 var 全局变量,在学习ES6后,我们学到了新的十分实用的另外两个变量 let 和 const
1.三者的不同点
1.作用域
· var 是全局作用域,在函数内部和外部都可以调用使用
· let 和 const 都是块级作用域,只在声明它们的函数内部使用
2.变量提升
· var 作为全局作用域,无论它声明时“身处何方”,在使用时都会被“第一眼看到”,会被自动视为声明在函数的最顶部
· let 和 const 不存在变量提升,因此必须先声明、定义再去使用,否则会报错
3.命名规范
· var 可以重复多次定义
· let 和 const 不能重复定义,否则会报错(避免了命名污染)
4.const的特殊之处
· const 声明的变量会被认为是常量,因此const声明的变量的值是不能二次更改的(基本数据类型的值不可更改)
· 但也有特例,当 const 是对象或者数组时可以对它里面的元素进行修改(复杂数据类型的内容可以更改但是不能给它重新赋值、改变它的地址)
注意: const 在声明时必须赋值才能使用
5.let 的暂时死区
· 只要和 let 在同一块区域,这块区域就会锁定,以let关键字为先,以以下代码为例:
var b = 10;
if (true) {
console.log(b);
let b = 20;
}
存在全局变量 b ,但是在块级作用域中 let 又声明了一个局部变量 b ,在这种情况下,使用的是 let 声明的变量,所以它的返回值应该是20
6.let 可以防止循环变量变成全局变量
以下面代码为例:
for (let i = 0; i < 2; i++) {
console.log(i);
}
console.log(i); // i is not defined
for (var j = 0; j < 2; j++) {
// console.log(j);
}
console.log(j);
解构
1.数组解构
数组解构允许我们按照一一对应的关系从数组中提取值 然后将值赋值给变量
let ary = [1, 2, 3];
let [a, b, c, d, e] = ary;
console.log(a) // 1
console.log(b) // 2
console.log(c) // 3
console.log(d) // undefined
console.log(e) // undefined
2.对象解构
对象解构允许我们使用变量的名字匹配对象的属性 匹配成功 将对象属性的值赋值给变量
let person = { name: 'lisi', age: 30, sex: '男' };
// let { name, age, sex } = person;
// console.log(name)
// console.log(age)
// console.log(sex)
let { name: myName } = person;
console.log(myName)
箭头函数
· 箭头函数是用来简化函数定义语法的
普通写法
function fn() {
console.log(10);
}
fn();
箭头函数写法
const fn = () => { console.log(10) };
fn();
· 箭头函数的可省略性
在箭头函数中,如果函数体只有一句代码并且代码的执行结果就是函数的返回值,那么函数体的大括号可以省略不写
const sum = (a, b) => a + b;
const result = sum(1, 2); // 用result去接收sum()函数计算得出来的值
console.log(result);
如果函数体只有一句话,那么它的 return 和 console.log() 可以省略
同理,在箭头函数中,如果形参只有一句代码并且代码的执行结果就是函数的返回值,那么形参的小括号可以省略不写
const fn = u => {
alert('tell me your name');
}
fn();
· 箭头函数中自己没有this
// 箭头函数中自己没有this,它的this指向包含它的区域,也就是它的this指向上下文
// 注意:this 是静态的 this 始终指向 函数声明时 所在作用域的this值
function fn() {
console.log(this); // 同样的。这也指向调用它的fn()函数
return () => {
console.log(this); // 这个的this指向的是fn()函数
}
}
const obj = { name: '王麻子' };
const result = fn.call(obj); // call() 改变this指向
result();
· 箭头函数不能作为构造函数来实例化对象
let Person = (name, age) => {
this.name = name;
this.age = age;
}
let you = new Person('zhangsan', 18);
console.log(you); // Person is not a constructor
· 箭头函数不能使用argument变量
let fn = () => {
console.log(argument);
}
fn(1, 2); // argument is not defined
参数默认值
· ES6 允许我们给函数的形参赋值
1.初始化形参 一般是给后面的形参赋初值,如果在前面赋初值可能作用不大
当形参的位置没有传参进来,它就会使用我们手动赋给它的初值;如果有传参自然以一传入的参数来进行计算
function add(a, b, c = 5) {
return a + b + c;
}
let result = add(1, 2);
console.log(result);
2.与解构赋值结合使用
function connect({ host, user, password, part }) {
console.log(host);
console.log(user);
console.log(password);
console.log(part);
}
connect({
host: 'lf.mic',
user: 'root',
password: 'root',
part: 1101
}) // 调用函数并传参进去
rest参数和拓展运算符
· rest 参数
rest 参数的使用和扩展运算符的运算几乎是一模一样
rest 参数表示: ...
rest 参数用于获取实参 代替了arguments (ES6时期引入的)
注意:argument 是一个对象因此它的返回值也是一个对象 rest 参数返回值是一个数组,因此可以使用数组的相关应用(filter、some等)
// 比较:
// ES5 获取参数的方法
// function data() {
// console.log(arguments);
// }
// data('小张张', '真源儿', '笨蛋真源');
// ES6 获取参数
// function data(...args) {
// console.log(args);
// }
// data('小张张', '真源儿', '笨蛋真源');
// rest 参数必须放在最后
function fn(a, b, ...c) {
console.log(a);
console.log(b);
console.log(...c);
}
fn(1, 2, 3, 4, 5, 6, 7, 8, 8, 9);
// 不同点:1.它的结果不会以逗号分隔而是直接输出来
// 2.rest 参数是放在函数形参的位置,而扩展运算符是放在函数传参的位置,即实参的位置
· 扩展运算符
扩展运算符表示: ...
1.扩展运算符可以用来合并数组
// 方法一:新建一个数组
// let arr1 = [1, 2, 3, 4];
// let arr2 = [5, 6, 7];
// let arr3 = [...arr1, ...arr2];
// console.log(arr3);
// 方法二:利用push方法,因为push方法中的对象也是用逗号分隔开来的,所以可用于合并数组
// let arr1 = [1, 2, 3, 4];
// let arr2 = [5, 6, 7];
// arr1.push(...arr2);
// console.log(arr1);
2.扩展运算符可以将伪数组转换为真正的数组,从而就可以使用数组的便捷方式
var oDivs = document.getElementsByTagName('div');
console.log(oDivs); // 此时它还是伪数组的形式
var arr = [...oDivs];
console.log(arr); // 此时它已经是真正的数组了
arr.push(1);
console.log(arr);
Symbol
· Symbol创建的变量是唯一的
创建方法:
// 创建 Symbol
// 1.直接创建
let s = Symbol();
// console.log(typeof s); // symbol
// 2.传参进去 (里面的参数就相当于一个标志,因此即使有其他的Symbol类型的值里面的描述字符串是一样的,他们的地址也是不一样的,“值”实际上也是不一样的)
let s2 = Symbol('尚硅谷');
let s3 = Symbol('尚硅谷'); // 这里的Symbol是一个函数
console.log(s2 === s3); // false
// 3.Symbol.for 方法创建
let s4 = Symbol.for('尚硅谷') // 此时这里的Symbol是一个对象 ,因此我们称 Symbol.for() 为:函数对象
let s5 = Symbol.for('尚硅谷')
// 通过这种方法创建的它的“地址”是一样的
console.log(s4 === s5); // true
// 注意:Symbol 不能与其他数据进行运算(对比、比较也不可以!)
· Symbol 可以为对象添加属性和方法
// let game = {
// name: '俄罗斯方块'
// }
// 方法一:
// 声明一个对象
// let methods = {
// up: Symbol(),
// down: Symbol()
// };
// // 给对象属性赋值
// game[methods.up] = function () {
// console.log('上上上上');
// }
// game[methods.down] = function () {
// console.log('下下下下');
// }
// console.log(game);
// 方法二:
let yule = {
name: '微博',
[Symbol('active')]: function () {
console.log('发微博了!');
},
[Symbol('happyTime')]: function () {
console.log('张哥的清唱时刻');
}
}
console.log(yule);
模板字符串
模板字符串:ES6 新增的创建字符串的一种方式,使用 `` 反引号进行定义
· 模板字符串可以解析变量
// let set = ` 这是一个模板字符串 `;
// console.log(set);
// let name = `张三`;
// let say = `嗨害,我是${name},你好呀`;
// console.log(say);
// 注意:是 `` 反引号 不是引号,符号不同,表达效果也截然不同
· 模板字符串可以换行
// let msg = {
// name: `李四`,
// age: 18
// };
// let html = `
// <div>
// <span>${msg.name}</span>
// <span>${msg.age}</span>
// </div>
// `;
// console.log(html);
· 模板字符串可以调用函数,也可以直接进行变量拼接
const fn = () => {
return "又要上课了,真开心";
}
let a = `六点一十了已经,${fn()}`;
console.log(a);
// ${} 是用来调用模板字符串的
// 注意:在单引号和双引号中书写的内容是不允许有换行的存在的,但是模板字符串内部可以换行
Set数据结构和Map数据结构
· set 数据结构 类似于数组,但是它的值都是唯一的
具体代码如下,请仔细观看:
// set 本身是一个构造函数 因此可以用来生成数据结构
// 注意:因为是构造函数,所以需要实例化对象 new 一下
// const s1 = new Set();
// console.log(s1.size);
// const 只阅读不能更改,可以一定程度的将它看作一个常量,当然声明常量用的就是它
// size 判断内容的长度
// set 函数可以接受一个数组作为参数,用来初始化
// const s2 = new Set(['a', 'b', 'c', 'd']);
// console.log(s2);
// console.log(s2.size);
// // set 会自动去重 因此可以用作数组去重
// const s3 = new Set(['a', 'a', 'c', 'c']);
// // console.log(s3.size); // 2
// let arr = [...s3];
// console.log(arr); // a c
// // 运用扩展运算符将s3里面的所有数据获取过来,并且将其转换为数组形式输出
// set.add() 增 返回数组本身
const s4 = new Set();
s4.add('a').add('d'); // 可链式调用
console.log(s4.size);
// set.delete() 删 返回的是布尔值
const r1 = s4.delete('a');
console.log(s4.size);
console.log(r1); // true
// set.has() 查 检查数组中是否有检索的元素 返回的是布尔值
const r2 = s4.has('b');
console.log(r2);
// set.clear() 清空所有内容 无返回值
s4.clear();
console.log(s4.size);
// 利用forEach()遍历set数据结构 从而获取值
const s5 = new Set(['a', 'b', 'c']);
s5.forEach(value => {
console.log(value);
})
// 注意:set 输出结果仍是以数组形式 因此它里面的数据类型还是有影响的,例如:数字型的值和字符串类型的值是不一样的,因此即使set有自动去重的功能,数据类型不同的两个数还是不会被删除的
· map 数据结构 类似于对象 是以键值对的方式来进行运算的 可以说它是键值对的集合,各个类型的值(包括对象)都可以用来当作键
具体代码如下,请仔细观看:
// map 与 set 相同,也是构造函数,可以用来生成数据结构
// 变量.set() 增
const a = new Map();
a.set('name', ['宋柏彦', '唐黎']);
a.set('age', 32);
a.set('sex', '男');
console.log(a.size);
// 变量.set() 改
// 当之前已经存在的元素“再次出现” set 就是 承担一个“改”的角色,将之前的数据覆盖,使之始终呈现最新的数据
a.set('age', 24);
// console.log(a);
// 变量.delete() 删
console.log(a.delete('age'));
// 返回值是 true 和 false
// 变量.get() 查
console.log(a.get('name'));
// 变量.clear() 清空所有数据
a.clear();
console.log(a);
// 练习
// 1.判断代码的输出值
const set = new Set();
set.add(1);
set.add(1);
set.add('1');
console.log(set); // 返回值是 1 '1' 两个1的类型不同
// 2.创建一个map 添加以下数据: 1:"北京" 2:"上海" 3:"湖南" 并且删除第一个元素
const cities = new Map();
cities.set(1, "北京");
cities.set(2, "上海");
cities.set(3, "湖南");
// console.log(cities);
cities.delete(1);
console.log(cities);
至此,小编目前学习的有关ES6的大部分知识以总结完了,小编正在“快马加鞭”的学习,光看不过瘾,赶紧动手来试试吧,没有什么解说能够代替亲身体验
如有错误,请在评论区中指正,我们共同进步!