ES6 笔记

var:它是variable的简写,可以理解成变量的意思。
let:let是局部变量声明,防止数据污染,let声明只在区块内起作用,外部是不可以调用的。
const:它在英文中也是常量的意思,在ES6用来声明常量的,常量可以简单理解为不变的量,从声明开始,这个变量始终不变。

变量的解构赋值

ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。

  1. 数组的解构赋值

按照位置的对象关系对变量赋值,数组模式和赋值模式统一
理解为等号左边和等号右边的形式要统一,如果不统一解构将失败。

let a=0;
let b=1;
let c=2;
⬇️⬇️⬇️⬇️⬇️⬇️
let  [a,b,c]=[1,2,3];
let [a,[b,c],d]=[1,[2,3],4];
  1. 解构的默认值

解构赋值是允许你使用默认值的
注意的是undefined和null的区别。

let [a,b="你好"]=['xjl']
console.log(a+b); 
//控制台显示“xjl你好”

let [a,b="你好"]=['xjl',undefined]
console.log(a+b); 
//控制台显示“xjl你好” undefined相当于什么都没有,b是默认值。

let [a,b="你好"]=['xjl',null]
console.log(a+b); 
//控制台显示“xjlnull” null相当于有值,但值为null。所以b并没有取默认值,而是解构成了null。

  1. 对象的解构赋值

解构不仅可以用于数组,还可以用于对象。

let {name,sex} = {name:'xjl',sex:'男'};
console.log(name+sex); //控制台打印出了“xjl男”

注意:对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

  1. 圆括号的使用

如果在解构之前就定义了变量,这时候你再解构会出现问题。
在解构的语句外边加一个圆括号就可以解决

let a;
({a} ={a:'1'});
console.log(a); //控制台输出1

[(b)] = [3]; // 正确
({ p: (d) } = {}); // 正确
[(parseInt.prop)] = [3]; // 正确
不能使用圆括号的情况

(1)变量声明语句
(2)函数参数也属于变量声明,因此不能带有圆括号。
(3)赋值语句的模式

  1. 字符串解构

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

let [a,b,c]="xjl";
console.log(a);
console.log(b);
console.log(c);
  1. 对象的函数解构

let xjl = {
    sex:'男',
    age:18
}
function fun({sex,age}){
    console.log(sex,age); //  男 18
}
fun(xjl);
  1. 数组的函数解构

let arr = ['xjl','男','18'];
function fun(a,b,c){
    console.log(a,b,c);  // xjl 男 18
}
fun(...arr);

扩展运算符和rest运算符

扩展运算符和rest运算符,它们都是(…)三个点,解决参数和对象数组未知情况下的编程

  1. 对象扩展运算符

当编写一个方法时,我们允许它传入的参数是不确定的。这时候可以使用对象扩展运算符来作参数

例1
function fn(...val){
    console.log(val[0]);
    console.log(val[1]);
    console.log(val[2]);
    console.log(val[3]);
}
fn(1,2,3);
//控制台输出:1,2,3,undefined,这说明是可以传入多个值,并且就算方法中引用多了也不会报错。

例2
let arr1=['x','j','l'];
let arr2=arr1;
console.log(arr2);  //["x", "j", "l"]
arr2.push('nihao');
console.log(arr1);//["x", "j", "l", "nihao"]

//发现arr1的值也改变了,因为我们这是对内存堆栈的引用,而不是真正的赋值。

例3 利用对象扩展运算符简单的解决例二问题

let arr1=['x','j','l'];
let arr2=[...arr1];
arr2.push('nihao');
console.log(arr2);  //["x", "j", "l", "nihao"]
console.log(arr1);//["x", "j", "l"]
  1. rest运算符 =剩余部分

for…of的循环可以避免我们开拓内存空间,增加代码运行效率

function arr(first,...arg){
    for(let val of arg){
        console.log(val);// 输出 1,2,3
    }
}
arr(0,1,2,3,);

字符串模版

  1. 字符串拼接

字符串模版不再使用‘xxx’这样的单引号 变用反引号 【`】
引用变量就需要用 ${xxx}
里边支持html标签,运算表达式,函数
换行和空格都是会被保留的

let a=1;
let b=2;
let name='xjl';
function f(){
  return "have fun!";
}
let  text= `你好我是${name}${a+b},${f()}`;
console.log(text);// 输出 你好我是xjl3,have fun!
  1. 字符串查找

支持中文
includes():返回布尔值,判断是否找到参数字符串。
startsWith():返回布尔值,判断参数字符串是否在原字符串的头部。
endsWith():返回布尔值,判断参数字符串是否在原字符串的尾部。
注意:这三个方法只返回布尔值,如果需要知道子串的位置,还是得用 indexOf 和 lastIndexOf 。starts和ends 后边都要加s

repeat(num) : 返回新的字符串,表示将字符串重复指定次数返回。

let text ='海阔凭鱼跃,天高任鸟飞。'

console.log(text.includes('鸟'))  //true
console.log(text.startsWith('海')) //true
console.log(text.endsWith('飞'))//false 结尾为【。】
console.log(text.repeat(2))//海阔凭鱼跃,天高任鸟飞海阔凭鱼跃。天高任鸟飞
  1. 字符串补全

padStart:返回新的字符串,表示用参数字符串从头部(左侧)补全原字符串。
padEnd:返回新的字符串,表示用参数字符串从尾部(右侧)补全原字符串。
以上两个方法接受两个参数,
第一个参数是指定生成的字符串的最小长度,
第二个参数是用来补全的字符串。

console.log("h".padStart(5,"o"));  
// "ooooh"
console.log("h".padEnd(5,"o"));    
// "hoooo"
console.log("h".padStart(5));     
 // "    h" 如果没有指定第二个参数,默认用空格填充。
console.log("hello".padStart(5,"A")); 
 // "hello" 如果指定的长度小于或者等于原字符串的长度,则返回原字符串
console.log("hello".padEnd(10,",world!"));  
// "hello,worl" 如果原字符串加上补全字符串长度大于指定长度,则截去超出位数的补全字符串

数组

  1. Array.from() JSON数组格式转换数组

let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
//带有length属性这种特殊的json格式都可以轻松使用ES6的语法转变成数组。
};

// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']

// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
  1. Array.of() 负责把一堆文本或者变量转换成数组。

Array.of(3, 11, 8) // [3,11,8]
Array.of(3,'aa') // [3,'aa']
Array.of(3).length // 1
  1. 数组实例的 find() 和 findIndex()

数组实例的find() 方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined。

[1, 5, 10, 15].find(function(value, index, arr) {
  return value > 9;
}) // 10

/*
value:表示当前查找的值。
index:表示当前查找的数组索引。
arr:表示当前数组。
*/

数组实例的findIndex()方法的用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。

[1, 5, 10, 15].findIndex(function(value, index, arr) {
  return value > 9;
}) // 2
  1. fill( )实例方法

把数组进行填充,它接收三个参数,第一个参数是填充的变量,第二个是开始填充的位置,第三个是结束填充的位置。
注意,如果填充的类型为对象,那么被赋值的是同一个内存地址的对象,而不是深拷贝对象。

['a', 'b', 'c'].fill(7, 1, 2)
//  ['a', 7, 'c'] fill方法从 1 号位开始,向原数组填充 7,到 2 号位之前结束。
  1. for…of循环

entries(),keys()和values()——用于遍历数组。
它们都返回一个遍历器对象,唯一的区别是
keys()是对键名的遍历、
values()是对键值的遍历,
entries()是对键值对的遍历。

for (let index of ['a', 'b'].keys()) {
  console.log(index);
}
// 0
// 1

for (let elem of ['a', 'b'].values()) {
  console.log(elem);
}
// 'a'
// 'b'

for (let [index, elem] of ['a', 'b'].entries()) {
  console.log(index, elem);
}
// 0 "a"
// 1 "b"

箭头函数

let 方法名 = 参数 => 代码块;


var f = v => v;
// 等同于
var f = function (v) {
  return v;
};

如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。

var f = () => 5;
// 等同于
var f = function () { return 5 };


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

如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。

var sum = (num1, num2) => { return num1 + num2; }

由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。

// 报错
let getTempItem = id => { id: id, name: "Temp" };

// 不报错
let getTempItem = id => ({ id: id, name: "Temp" });

如果箭头函数只有一行语句,且不需要返回值,可以采用下面的写法,就不用写大括号了。

let fn = () => void doesNotReturn();

箭头函数可以与变量解构结合使用。

const full = ({ first, last }) => first + ' ' + last;

// 等同于
function full(person) {
  return person.first + ' ' + person.last;
}

箭头函数使得表达更加简洁。

const isEven = n => n % 2 === 0;
const square = n => n * n;

箭头函数有几个使用注意点。

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

上面四点中,第一点尤其值得注意。this对象的指向是可变的,但是在箭头函数中,它是固定的。

in的用法

in是用来判断对象或者数组中是否存在某个值的。

  1. 对象判断

let xjl={
    sex:'男',
    age:'18'
}
console.log('age' in xjl);  //true
  1. 数组判断

ES5判断的弊端,以前会使用length属性进行判断,为0表示没有数组元素。但是这并不准确,或者说真实开发中有弊端

// ES5判断
let arr=[,,,,,];
console.log(arr.length); //5

//ES6判断
let arr=[,,,,,];
console.log(0 in arr); //false

let arr1=['男','18'];
console.log(0 in arr1);  // true

注意:这里的0指的是数组下标位置是否为空。

数组遍历

  1. forEach

forEach循环的特点是会自动省略为空的数组元素,相当于直接给我们筛空了。当然有时候也会给我们帮倒忙。

let arr=['男','18'];
arr.forEach((val,index)=>console.log(index,val));
// 0 "男"  1 "18"
  1. filter & some

let arr=['男','18'];
arr.filter(x=>console.log(x));  //男 18
arr.some(x=>console.log(x));  //男 18
  1. map

map在这里起到一个替换的作用

let arr=['男','18'];
console.log(arr.map(x=>'aa'));  //["aa", "aa"]

数组转换字符串

  1. join()方法

数组元素中间,加了一些指定符号进行间隔,开发中很有用处。

let arr=['男','18'];
console.log(arr.join('|'));  //男|18
  1. toString()方法

转换时只是是用逗号隔开了。

let arr=['男','18'];
console.log(arr.toString());  //男,18

ES6 对象

  1. 对象赋值

ES6允许把声明的变量直接赋值给对象

let name="xjl";
let age= '18';
var obj= {name,age};
console.log(obj);  //Object {name: "xjl", age: "18"}
  1. 对象 key值构建

有时候我们会在后台取出key值,而不是我们前台定义好的,这时候我们如何构建我们的key值那。比如我们在后台取了一个key值,然后可以用[ ] 的形式,进行对象的构建。

let key='name';
var obj={
    [key]:'xjl'
}
console.log(obj.name); //xjl
  1. 自定义对象方法

对象方法就是把对象中的属性,用匿名函数的形式编程方法。

const obj = {
  add(a,b) {
    return a+b;
  }
};
console.log(obj.add(1,2));  //3

// 等同于

const obj = {
  add: function(a,b) {
    return a+b;
  }
};
  1. Object.is( ) 对象比较

=== 和 is方法的区别:===为同值相等,is()为严格相等。

var obj1 = {name:'xjl'};
var obj2 = {name:'xjl'};
console.log(obj1.name === obj2.name);//true 
console.log(Object.is(obj1.name,obj2.name)); //true

console.log(+0 === -0);  //true
console.log(NaN === NaN ); //false
console.log(Object.is(+0,-0)); //false
console.log(Object.is(NaN,NaN)); //true

  1. Object.assign( )合并对象

let a={a:'xjl'};
let b={b:'男'};
let c={c:'18'};

let d=Object.assign(a,b,c)
console.log(d);  // {a: "xjl", b: "男", c: "18"}

ES6 Symbol类型

  1. Symbol声明

let g = Symbol('xjl');
console.log(g);
console.log(g.toString());
// 这时候我们仔细看控制台是有区别的,没有toString的是红字,toString的是黑字。
  1. Symbol在对象中的应用

Symbol构建对象的Key,并调用和赋值。

var xjl = Symbol();
var obj={
    [xjl]:'徐佳乐'
}
console.log(obj[xjl]);
obj[xjl]='web';
console.log(obj[xjl]);
  1. Symbol对象元素的保护作用

在对象中有很多值,但是循环输出时,并不希望全部输出,那我们就可以使用Symbol进行保护。

let obj={name:'xjl',sex:'男',age:18};
for (let item in obj){
    console.log(obj[item])  // xjl   男   18
}

//现在我不想别人知道我的年龄,这时候我就可以使用Symbol来进行循环保护。

let obj={name:'xjl',sex:'男'};
let age=Symbol();
obj[age]=18
for (let item in obj){
    console.log(obj[item])  // xjl   男 
}
console.log(obj)  // {name: "xjl", sex: "男", Symbol(): 18}

Set和WeakSet数据结构

Set数据结构,注意这里不是数据类型,而是数据结构。它是ES6中新的东西,并且很有用处。Set的数据结构是以数组的形式构建的。

  1. Set 声明

Set和Array 的区别是Set不允许内部有重复的值,如果有只显示一个,相当于去重。虽然Set很像数组,但是他不是数组。

let setArr = new Set(['xjl','男','18']);
console.log(setArr);//Set {"xjl", "男", "18"}
  1. Set值的增删查清空

add,delete,has
用has进行值的查找,返回的是true或者false。

let setArr = new Set(['xjl','男','18']);
console.log(setArr);//Set {"xjl", "男", "18"}
setArr.add('好孩子') 
console.log(setArr);//Set {"xjl", "男", "18","好孩子"}
setArr.delete('好孩子')
console.log(setArr);//Set {"xjl", "男", "18"}

console.log(setArr.has('男'));// true

setArr.clear()
console.log(setArr);//Set {}

  1. 循环 & size属性

size属性可以获得Set值的数量。

let setArr = new Set(['xjl','男','18']);
// forEach & for..of 循环
setArr.forEach((value)=>console.log(value));
// xjl   男  18

for (let item of setArr){
    console.log(item); // xjl   男  18
}
console.log(setArr.size); // 3
  1. WeakSet的声明

这里需要注意的是,如果你直接在new 的时候就放入值,将报错

let weakObj=new WeakSet();
let obj={name:'xjl',sex:'男',age:'18'}
weakObj.add(obj);
console.log(weakObj);
// WeakSet {{…}}

map数据结构

map是一种灵活,简单的适合一对一查找的数据结构;我们知道的数据结构,已经有了json和set。
map特点:key => value
一种特殊的键值对,key可以设置成数组,值也可以设置成字符串,让它不规律对应起来。当然也可key字符串,value是对象。

let json = {
    name:'xjl',
    age:18
}
var map=new Map();
map.set(json,'iam');
console.log(map);
// {{…} => "iam"}  {Object => "iam"}  key: {name: "xjl", age: 18} value: "iam"

map.set('iam',json);
console.log(map);
// {"iam" => {…}}  {"iam" => Object} key: "iam" 
 value: {name: "xjl", age: 18

map的增删查 同 set ,取json对应的值 map.get()

用Proxy进行预处理

什么是钩子函数。当我们在操作一个对象或者方法时会有几种动作,比如:在运行函数前初始化一些数据,在改变对象值后做一些善后处理。这些都算钩子函数,Proxy的存在就可以让我们给函数加上这样的钩子函数,你也可以理解为在执行方法前预处理一些代码。你可以简单的理解为他是函数或者对象的生命周期。

Proxy的应用可以使函数更加强大,业务逻辑更加清楚,而且在编写自己的框架或者通用组件时非常好用。

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。

// 回顾一下定义对象的方法。
let obj = {
  add(val) {
    return val+10;
  },
   name:'xjl'
};

let target = {name:'xjl'}

console.log(obj.add(10));  //20
console.log(obj.name); //xjl
console.log(target.name); //xjl
  1. 声明Proxy

需要注意的是这里是两个花括号,
第一个花括号就相当于我们对象方法的主体,
第二个花括号就是Proxy代理处理区域,相当于我们写钩子函数的地方。

new Proxy({},{});

let target = {name: 'xjl'}
let handler = {
    get(target, propKey, receiver) {
        return target[propKey]
    },
    set(target, propKey, value, receiver) {
        return target[propKey] = value;
    }
}
let pro = new Proxy(target, handler)

console.log(pro.name) //xjl
pro.name = '徐乐乐';
console.log(pro.name); // 徐乐乐

get(target, propKey, receiver):拦截对象属性的读取;
set(target, propKey, value, receiver):拦截对象属性的设置,比如pro.name='徐乐乐';

target:目标对象。
propKey:目标对象的Key值 属性名。
value:要改变的对象属性值。
receiver:改变前的原始值。 (可忽略)

promise对象的使用

ES6中的promise的出现给我们很好的解决了回调地狱的问题
promise执行多步操作非常好用,那我们就来模仿一个多步操作的过程,那就以吃饭为例吧。要想在家吃顿饭,是要经过三个步骤的。
1.洗菜做饭。
2.坐下来吃饭。
3.收拾桌子洗碗。
这个过程是有一定的顺序的,你必须保证上一步完成,才能顺利进行下一步。

let state = 1;//定义状态码

/*三个 动作方法*/
const step1 = (resolve, reject) => {
    console.log('1.开始-洗菜做饭');
    if (state == 1) {
        return resolve('洗菜做饭--完成');
    } else {
        return reject('洗菜做饭--出错');
    }
}
const step2 = (resolve, reject) => {
    console.log('2.开始-坐下来吃饭');
    if (state == 1) {
        return resolve('坐下来吃饭--完成');
    } else {
        return reject('坐下来吃饭--出错');
    }
}

const step3 = (resolve, reject) => {
    console.log('3.开始-收拾桌子洗完');
    if (state == 1) {
        return resolve('收拾桌子洗完--完成');
    } else {
        return reject('收拾桌子洗完--出错');
    }
}

new Promise(step1).then((value) => {
    console.log(value);
    return new Promise(step2);
}).then(
    (value) => {
        console.log(value);
        return new Promise(step3);
    }
).then(
    (value) => {
        console.log(value);
        return value;
    }
)

/*
1.开始-洗菜做饭
洗菜做饭--完成
2.开始-坐下来吃饭
坐下来吃饭--完成
3.开始-收拾桌子洗完
收拾桌子洗完--完成*/

class 类的使用

ES5中经常使用方法或者对象去模拟类的使用,虽然可以实现功能,但是代码并不优雅,ES6为我们提供了类的使用。需要注意的是我们在写类的时候和ES5中的对象和构造函数要区分开来,不要学混了。


class Boy {
    age = (value) => {
        console.log(value)
        return value;
    }
    name = (value) => console.log(` ${value} 今年 ${this.age('18')}了`)

    constructor(a, b) {
        this.a = a;
        this.b = b;
    }

    add = () => this.a + this.b
}

let xjl = new Boy(10, 20); // 用constructor来约定了传递参数,实例化类的时候传进参数
xjl.name('徐乐乐') // 18=name方法里调用了age方法打印得   徐乐乐 今年 18了=name方法得出
console.log(xjl.add()) //30


/*声明一个Girl的新类并继承Boy类,Girl新类里边为空,
这时候我们实例化新类,并调用里边的name方法。结果也是可以调用到的。*/

class Girl extends Boy {

}

let ygg = new Girl;
ygg.name('于乖乖')

两个方法中间不用写逗号
用this调用类里面的其他方法,这里的this指类本身,还有要注意return 的用法
在类的参数传递中我们用constructor( )约定进行传参。传递参数后可以直接使用this.xxx进行调用。
class Girl extends Boy 关键词 extends

模块化操作 export & export defalut

export :负责进行模块化,也是模块的输出。
import : 负责把模块引,也是模块的引入操作。

  1. export 用法

export可以让我们把变量,函数,对象进行模块话,提供外部调用接口,让外部进行引用。先来看个最简单的例子,把一个变量模块化。我们新建一个a.js文件,然后在文件中输出一个模块变量或者多个。

export let name = 'xjl'; // 单个变量输出

let age = '18'
let sex = '男';
export {age, sex}   // 多变量的输出 包装成对象

//函数的模块化输出
export function add(a, b) {
    return a + b;
}

然后可以在b.js中以import的形式引入。
必须用{},必须知道输出文件里的模块名

import {name,age,sex,add} from './a;


console.log(name) // xjl
console.log(age) //18
console.log(sex)// 男
console.log(add(1, 2))  //3
  1. export defalut 用法

加上default相当是一个默认的入口。在一个文件里export default只能有一个

export default let name='xjl';

对应的引入方式
不需要{} 名字自定义

import xxx from './a;

你可能感兴趣的:(ES6 笔记)