一、块级作用域
(1)let 、const、var的区别
1、var
es6之前,一般都是使用var进行变量声明,不管在上面地方进行声明,都会将变量推升到函数的最顶部(不在函数内及在全局作用域最顶部)。实际就是变量提升。如:
function test(){
if(bool){
var test = 'hello World';
}else{
console.log(test);
}
}
// 实际上
function test(){
var test; //预编译,变量提升
if(bool){
test = 'hello World';
}else{
// 此处访问test 为undefined
console.log(test);
}
}
实际上不用关心boo是否为false或true,var test都会被提升、创建。
2、let、const命令--->命名参数带有块级作用域,通常会用let来命名变量,const来命名常量。什么是块级作用域?
(1) 一个在代码块内部。
简单的来说{}内部的作用域就是let和const的代码块。
举一个经典面试题:说出执行结果是多少。
for(var i = 0; i < 10; i++){
setTimeout(function(){
console.log(i)
},100 * i)
}
很多人一看就知道执行结果为10,那么如果我们想输出0-9,怎么实现
//es5方法,利用立即执行函数解决闭包问题
for(var i = 0; i < 10; i++){
(function(j){
setTimeout(function(){
console.log(j)
},100 * j)
})(i)
}
//es6
for(let i = 0; i < 10; i++){
setTimeout(function(){
console.log(i)
}, 100 * i)
}
二、变量的解构赋值
1、数组的解构赋值 ----->实质:模式匹配 index下标对应
//解构成功
var [a, b, c] = [1, 2, 3] //a = 1, b = 2, c = 3
//解构不成功
var [a, b] = [2] //a = 2, b = undefined 没赋值,故为undefined
//不完全解构
var [a, b] = [1, 2, 3] //a = 1, b = 2, c未定义,故没有
//默认赋值
var [a = 10, b = a] = [] //a = 10, b=10
var [a = 10, b = a] = [2] //a = 2, b = 2 //如果有赋值,则为2,没赋值则为默认值10
2、对象的解构赋值--->实质:模式匹配
let {bar : bar1 , foo : foo1} = {bar : 123, foo : 465} //bar1 = 123, foo1 = 456
// bar 、foo为匹配模式,bar1、foo1位匹配值,对象解构赋值,看的是匹配模式,所有bar、foo顺序可以不一致。
//默认值
let {x = 0, y = 0} = {} //x = 0, y = 0 同数组解构默认值
三、字符串的扩展
1、模板字符串 => ``反引号 =>相当于增强的字符串
var obj = {
age : 12,
name: 'xiaoming',
sex : 'male'
}
let {age,name,sex} = obj;
// es5
var obj2 = 'name:' + name + ' age:' + age + ' sex:' + sex;
//es6
var obj1 = `name:${name} age:${age} sex:${sex}`;
上面结果输出都是一样的,相比之下es6显得更加的简便
2、标签模板
标签模板不是模板,而是函数调用的一种特殊的形式。“标签”指的是函数,紧跟在后面的模板字符串就是它的参数。
var a = 5;
var b = 10;
tag `Hello ${a+b} world ${a*b}`;
//这个标识名tag,它是一个函数。整个表达式的返回值,就是tag函数处理模板字符串之后的返回值。函数tag会依次接收到多个参数。
function tag(s,v1,v2){
console.log(s[0]);
console.log(s[1]);
console.log(s[2]);
console.log(v1);
console.log(v2);
return "ok";
}
重要应用 ==> 就是过滤HTML字符串,防止用户输入恶意内容
3、函数的扩展
a、函数参数的默认值,传参就取参数,没传就去默认值。一旦有默认值,就用let声明,形成封闭的作用域
function show(age ,name = 'xiaoming'){
console.log(name,age)
}
show(12) //xiaoming 12
show(12,'zhagnsan') //zhangsan 12
四、箭头函数
1、 基本使用方法
//es5
function num(num){
return num;
}
//es6
var f = num => num;
es6的箭头函数相比于es5函数来说,书写更加简便。
2、箭头函数和普通函数的区别,举个栗子
function make () {
return ()=>{
console.log(this);
}
}
var testFunc = make.call({ name:'foo' });
testFunc();
testFunc.call({ name:'bar' });
//执行结果
//Object {name: "foo"}
//Object {name: "foo"}
可以看到箭头函数在定义之后,this就不会发生改变,无论用什么方式进行调用,this都不会改变
原因:箭头函数不会自动绑定局部变量,如this,arguments,super(ES6),new.target(ES6)等
所以箭头函数没有它自己的this值,箭头函数内的this值继承自外围作用域。在箭头函数中调用 this 时,仅仅是简单的沿着作用域链向上寻找,找到最近的一个 this 拿来使用
五、数组的扩展
1、数组:扩展运算符
var arr = [1,2,3,4,5]
function fn(...args){
console.log(arguments);
}
fn.call(null,...arr) // 1,2,3,4,5
作用,去掉中括号
2、字符串:相当于用split(",")将字符串给分开
3、Array.from() --->将类数组转化为数组
var obj = {
0 : 0,
1 : 'a',
2 : 'b',
3 : 3,
length : 4
}
let arr = Array.from(obj); //arr=[0,'a','b',3]
4、Array.of()---->将数字串转化为数组
var str = 12345;
let arr = Array.of(str) // arr = [1,2,3,4,5]
//源码封装
function arrayof(){
return Array.prototype.slice.call(arguments);
}
5、copyWithin() --->返回新数组,修改原数组
var arr = [1,2,3,4,5]
let arr1 = arr.copyWithin(0,3,4) //arr1= [4,2,3,4,5]
//0为设置修改起始位子,3为复制起始点,4位复制结束。也可以设置为负数(从尾开始)
6、entries() keys() values()
//entries() 使用迭代器循环
var arr = [1,2,3,4,5]
for([item,index] of arr.entries()){
console.log(item,index)
}
//返回keys值和values值
for(index of arr.keys()){
console.log(index)
}
//返回keys值
for(item of arr.values()){
console.log(item)
}
//返回values值
7、includes() find() findIndex()
var arr = [1,2,3,4,5]
let arr1 =arr.includes(2)
console.log(arr1);
//查看数组书否包含元素,是返回true,否返回false;
var arr = [1,2,3,4,5]
let arr1 =arr.find(item => item> 1)
console.log(arr1);
//查找元素并返回元素 findIndex()同理,查找下标
六、对象扩展
1、Object.is() ---->相当于增强的===
2、Object-assign()合并对象
var obj = {}
var obj1 = {
name : 'xiaoming',
age : 18
}
var obj2 = {
sex : 'male'
}
Object.assgin(obj,obj1,obj2)
3、Object.keys() Obejct.values() Object.entries()
同数组.