es6学习
es6 变量的声明方式
let 关键字:
- 声明的变量是块级作用域
- 不允许重复声明变量
- 不存在变量提升
for(let i = 0; i < 5; i++){
setTimeout(() =>{
console.log(i)
}, 1000)
}
const 关键字:
- 声明的是块级作用域
- 不允许重复声明变量
- 不存在变量提升
- 声明的是一个常量(基本数据类型):本质 是 存放变量的内存地址不允许更改; 基本数据类型的数据和地址存放在栈中(存放在一起的), 因此变成常量, 常量不允许更改; 但是对于引用数据类型, 栈中存放的是地址(指针),地址指向堆内存空间,声明一个引用数据类型作为常量时, 相当于是固定了指针, 而不能固定数据
常见面试题: var, let 和const 三者的区别
- var 存在变量提升机制, let和const 不存在变量提升
- var 允许重复声明变量, let和const不允许重复声明变量
- var 声明的变量值可以随意更改,const 声明的是常量,不允许更改
- var 声明的变量会产生内存泄露,let 和 const 不会
- var 声明的变量是全局作用域或者局部作用域, let 和 const声明的变量是块级作用域
es5 数组的遍历(迭代)方式
以下两种循环方式可以使用 break 和continue 语句
- for循环
- for-in循环:可以遍历数组, 但是他最主要的功能是遍历对象
————————————————————————————
以下几种遍历方式不可以使用 break 和continue 语句
错误信息: Uncaught SyntaxError: Illegal break statement
错误信息: Uncaught SyntaxError: Illegal continue statement: no surrounding iteration statement - forEach()
- map() : 映射, 返回是一个新数组
- some() :返回一个布尔值, true: 只要数据中有一个元素满足条件即可
- every(): 返回一个布尔值, true: 数据中所有的元素满足条件即可 ;
- reduce(function(acc, value, index){}, initValue) : 累计器 ;如果提供初始值 initValue; 则acc 就是初始值,否则是数组中的第一个元素
- filter() : 过滤器 ; 返回的是一个新的数组(满足条件的)
是否使用return语句
- for循环,for-in, forEach() 他们三者不需要使用return语句
- map() some() every() reduce() filter() 他们需要借助于return语句
es6的箭头函数
使用 => 表示箭头函数
- 基本结构
let fun = () => {}
- 一个参数: () 可以省略
let fun = (x) => {
console.log(x)
}
let fun = x => {
console.log(x)
}
let fun = (x, y) => {
console.log(x, y)
}
- 返回值是单一的语句 : {} 可以省略, 如果返回值是对象, 需要添加 ()
let fun = x => x * x
let fun = () => ({
name:'tom',
age:18
})
es6的解构赋值
- 对象解构 : 按照对象的key(属性名)进行解构
// 按照默认键名进行解构
let {name, age} = {name:;'tom', age:18}
console.log(name, age) // tom 18
// 重新定义 解构名字
let {name:xm, age:nl} = {name:;'tom', age:18}
console.log(xm , nl) // tom , 18
- 数组解构 : 按照数组的顺序(索引值) 进行解构
let arr = [10, 30, 50];
// let [a] = arr;
let [a, , b] = arr;
// 结合 扩展运算符进行解构
let [a, ...b] = arr; // 正确 ...b 扩展运算符必须放到最后
let [...b, a] = arr; // 错误信息: Rest element must be last element
// 数组是按照索引值进行解构
let arr = [10, [23, 456]];
// let [a, b, c] = arr; // a ===> 10 ; b===> [23, 456] c===> undefined
let [a, [b, c]] = arr; // a ===> 10 ; b===> 23 c===> 456
console.log(a);
console.log(b);
console.log(c);
-
扩展运算符的应用
- 通过 扩展运算符 实现一维数组的深拷贝
let arr = [10, 30, 540]; let [...a] = arr; console.log(a); a[0] = 'hello'; console.log(arr);
- 通过 扩展运算符 实现 数组的合并
let arr = [10, 20], arr2 = [30, 50]; let res = [...arr, ...arr2] console.log(res);
- 通过 扩展运算符 求数组中的最大值和最小值
let arr = [10, 320, 546, 23]; // // let max = Math.max(...arr); // 原理是对数组进行解构为单一的值作为max()的参数 // // let min = Math.min(...arr); // let max = Math.max.apply(null, arr) // 原理利用函数对象的 apply() 方法调用执行Math.max() 方法并传参 (apply方法接受数组作为参数) let min = Math.min.apply(null, arr) // console.log(max, min);
-
函数参数解构 和默认值
通常情况下,定义了默认值的参数,应该是函数的尾参数;如果非尾部的参数设置默认值,实际上这个参数是没法省略的。
// 为函数的参数设置默认值,即直接写在参数定义的后面
function fun(x, y = 100){console.log(x, y)}
fun(100) // x ===>100 y===>100
fun(100, 200) // x ===>100 y===>200
// 使用参数默认值时,函数不能有同名参数。
function fun(x, x, y = 100){} // 报错
// 参数默认值可以与解构赋值的默认值,结合起来使用。
function foo({x, y = 5}) {
console.log(x, y);
}
fun({}) // undefined 5
fun({x:100}) // 100 5
fun({x:100, y:300}) // 100 300
fun() // 报错
//
es6的类和继承
***通过class 定义类 ***
class Person{
// 定义一个构造器 , 相当于我们之前讲的 构造函数 私有的属性
constructor(name, age){
this.name = name;
this.age = age;
}
// 定义公有的方法 添加到原型对象上
study(){
console.log('学习')
}
say(){
console.log('hello' + this.name)
}
}
***通过extends 继承; super()关键字 继承父类私有的属性 ***
class Student extends Person{
// 定义一个构造器 , 相当于我们之前讲的 构造函数 私有的属性
constructor(name, age, grade){
super(name, age);
this.grade = grade;
}
// 定义公有的方法 添加到原型对象上
study(){
console.log('自己学习')
}
}
Symbol() 数据类型
Symbol()提供了一个独一无二的值,是一个基本数据类型; 可以接受一个参数:用来区分
let count1 = Symbol('c1')
let count2 = Symbol('c2')
// 解决的问题: 对库(对象)进行扩展,又不用担心和库(对象)中的属性名冲突
let obj = {
name:'tom',
age:18,
count(){
console.log('统计计数')
}
}
// 借助Symbol()类型
let count = Symbol();
// 把 count 作为 obj 的属性 需要使用 []
obj[count] = function(){
console.log('扩展obj')
}
// 调用对象中的 Symbol() 创建的count 的方法
obj.count() // 调用对象自身的
obj[count](); // 调用对象中的 Symbol() 创建的count 的方法
遍历Symbol()属性名 :Symbol 作为属性名,遍历对象的时候
- 通过 Obejct.getOwnPropertySymbols() 遍历, 得到的是所有的Symbol() 属性名; 常规的属性名是获取不到的
- 通过 Reflect.ownKeys() 方法遍历对象的所有属性名 (常规和Symbol()的)
Set() 数据结构
set()是一个新的数据类型, 类似于数组,但是不能通过下标取值;set()值不允许重复
- 声明set() 数据类型
let set = new Set() // Set() 是一个构造函数 空的set()
let set = new Set([1, 1, 1, 2, 3, 5]) // 参数是数组, 要求值不能重复; 自动去重
- 通过set() 的特性 实现 数组去重
let arr1 = [1, 1, 1, 1, 2, 3]
let arr = [...new Set(arr1)]
-
set() 数据的操作
- add() : 添加
- delete() : 删除 ; 返回值是布尔值 true:删除成功。 false:删除失败
- clear() : 清空
- has() : 判断是否存在某个值; 返回值布尔值 true:存在 false:不存在
-
set() 进行遍历 : 由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致。
- keys() : 返回键名的遍历器
- values() : 返回键值的遍历器
- entries() : 返回键值对的遍历器
- forEach() : 使用回调函数遍历每个成员(类似数组中的forEach())
for-of 遍历 : 遍历部署了 [Symbol.iterator] 属性的数据
原生具有iterator接口的数据类型:
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
自定义对象不存在 该接口的, 不能使用for-of遍历 ; 如果要使用for-of遍历自定义对象,需要自己部署接口
Iterator迭代器 (接口)
- 一是为各种数据结构,提供一个统一的、简便的访问接口;
- 是一个函数
- Iterator 接口主要供for…of消费
- (原理) 每一次调用next方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含value和done两个属性的对象。其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。(false:意味着遍历没有结束; true:意味着遍历结束了, value属性的值 是undefined)
自定义对象 部署Iterator接口
let obj = {
name:'tom',
age:19,
say:'hello',
sleep:'睡觉',
[Symbol.iterator]: function(){
let index = 0; // 模拟指针移动
let key = null; // 存储键
let self = this; // 存储this
return {
next: function(){
if(key == null){
// key 是存储所有的键名 是一个数组
key = Object.keys(self)
}
return {
value:self[key[index]],
done:++index > key.length
}
}
}
}
}
// 没有部署之前 报错: obj is not iterable (obj 不可迭代的)
// for(let key of obj){
// console.log(key);
// }
// 执行的过程
let iterator = obj[Symbol.iterator]();
let res1 = iterator.next();
let res2 = iterator.next();
let res3 = iterator.next();
let res4 = iterator.next();
let res5 = iterator.next();
console.log(res1); // {value:tom, done:false}
console.log(res2); // {value:, done:false}
console.log(res3);
console.log(res4);
console.log(res5);
Object.keys() 方法 获取对象属性名的集合(结果是属性名组成的数组)(获取的是对象常规的属性名,不包含Symbol()类型)