一、let与const
const声明常量,会形成块级作用域,一旦声明后就无法更改。
const PI=3.14;
console.log(PI);//3.14
PI=1;
console.log(PI);//Identifier 'PI' has already been declared
复制代码
let与var都是用来声明变量,let声明变量时,会形成块级作用域,该变量仅能在此作用域内使用,且不会提升。它们的不同之处具体体现在:
1)、变量的提升
var:声明的变量不管在哪儿,都会被提升到函数的最上方
console.log(a);//undefined
var a=1;
//等价于
var a;
console.log(a);
a=1;
复制代码
let:声明的变量不会提升
console.log(a);//a is not defined
let a=1;
复制代码
2)、变量的覆盖
var:内部变量会覆盖外层变量
var a=1;
if(true){
var a=2;
console.log(a);
}
f();//2
console.log(a);//2
复制代码
let:形成块级作用域,不会污染全局变量
let a=1;
if(true){
let a=2;
console.log(a);//2
}
console.log(a);//1
复制代码
3)、循环变量泄露
var:循环变量会发生泄露,新的值会覆盖旧值
var arr=[];
for(var i=0;i<10;i++){
arr[i]=function(){
console.log(i);
}
}
arr[5]();//10 每一次循环i的值都会覆盖之前的值,打印的值为执行完循环体后i的值
复制代码
let:形成块级作用域,变量的值只能在作用域内,互不干扰
let arr=[];
for(let i=0;i<10;i++){
arr[i]=function(){
console.log(i);
}
}
arr[5]();//5 每次循环都会形成一个作用域,其中放置了i的值,不会发生新值覆盖旧值的情况
复制代码
二、箭头函数(arrow functions)
格式:()=>{ }
箭头函数的推出,方便了我们对函数的书写,逐渐成为我们写函数时最习惯的方式,下面就来看看箭头函数的使用
let a=(x)=>{
return x*2;
}
console.log(a(5));//10
//以上代码还可以简化。
//只有一个形参时可以去掉();
//函数体内只有一行代码时可以去掉{};
//一行代码如果是return语句,return可以省略
let a=x=>x*2;
console.log(a(5));//10
复制代码
注意:箭头函数没有this,它内部的this与外部的this是指向同一个对象
三、模板字符串(template string)
格式: ``
在里面的变量写法不用再拼接了,只需要用${}来划定范围就行了,大括号内部可以放入任意的 JavaScript 表达式,可以进行运算,以及引用对象属性。 如果使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中。
let name=" zhang san";
let age="20"
console.log(`我的名字是${name},今年${age}岁,明年${++age}岁`);//我的名字是 zhang san,今年20岁,明年21岁
复制代码
includes:判断是否包含然后直接返回布尔值; repeat: 获取字符串重复n次
let a="hello";
console.log(a.includes("ll"));//true
console.log(a.repeat(3));//hellohellohello
复制代码
四、class、extends、super
class(类) 格式:
class 类名{
constructor(参数){ //constructor构造方法,this指实例对象
this.属性=参数;
}
method(){ //简写方法,省略function
}
}
复制代码
注意: 1)、class 是关键字,后面紧跟类名,类名首字母大写,采取的是大驼峰命名法则。类名之后是{ }。 2)、在{ }中,不能直接写语句,只能写方法,方法不需要使用关键字 3)、方法和方法之间没有逗号。不是键值对
class使用extends关键字来实现继承,这相比与ES5通过原型链来继承更加清晰明了
super指代父类的实例(即父类的this对象),子类在constructor中调用super方法来获得this对象
class继承案例如下:
class NBAPlayer{
constructor(name,age,height){
this.name=name;
this.age=age;
this.height=height;
}
say(){
console.log(`我是${this.name},今年${this.age}岁,身高${this.height}cm`)
}
}
class MVP extends NBAPlayer{
constructor(name,age,height,year){
super(name,age,height);
this.year=year;
}
show(){
console.log(`${this.name}获得了${this.year}年的MVP`)
}
}
let person1=new MVP("杜兰特",30,211,2018);
person1.say();//我是杜兰特,今年30岁,身高211cm
person1.show();//杜兰特获得了2018年的MVP
复制代码
分析上面案例: 使用class创建了一个NBAPlayer构造器,接着我们创建了一个MVP构造器,使用extends实现继承NBAPlayer构造器,且通过调用super继承NBAPlayer构造器中的this对象。当我们需要创建一个新的对象时,通过new MVP(构造器)完成创建,就可以使用其中的方法了。
五、解构(destructuring)
对象字面量和数组字面量提供了一种简单的定义一个特定的数据组的方法。 解构赋值使用了相同的语法,不同的是在表达式左边定义了要从原变量中取出什么变量。
解构数组
右边的值直接赋给左边对应位置的变量
声明变量并赋值的解构
let [a, b] = [1, 2];
console.log(a); // 1
console.log(b); // 2
复制代码
为了防止从数组中取出一个值为undefined的对象,可以为这个对象设置默认值
let [a, b=5] = [1];
console.log(a); // 1
console.log(b); // 5
复制代码
忽略某些值
let [a,,b] = [1,2,3];
console.log(a); // 1
console.log(b); // 3
复制代码
变量互换
let a=1,b=2;
[a,b]=[b,a];
console.log(a); // 2
console.log(b); // 1
复制代码
解构对象
数组的解构是按次序排列的,变量取值由位置决定的,而对象的属性是没有顺序的,变量必须与属性同名才能取到正确的值。
声明对象,给属性赋值
var {p, q} = {p: 42, q: true};
console.log(p); // 42
console.log(q); // true
复制代码
给新变量命名并提供默认值
var {a:aa = 10, b:bb = 5} = {a: 3};
console.log(aa); // 3
console.log(bb); // 5
复制代码
六、数组扩展
扩展运算符
扩展运算符(spread)是三个点(...),作用是将一个数组转为用逗号分隔的参数序列。
console.log(1, ...[2, 3, 4], 5)// 1 2 3 4 5
复制代码
Array.from
Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
};
let arr = Array.from(arrayLike); // ['a', 'b', 'c']
复制代码
Array.of
Array.of可以将一组值转换成数组,由于它不存在由于参数不同而导致的重载,基本上可以用来替代Array()或new Array()。
Array.of(1, 2, 3) // [1,2,3]
复制代码
includes
includes用于判断元素是否在数组中存在,返回值是 true/false。
let arr=[1,2,3];
arr.includes(2);//true
arr.includes(5);//flase
复制代码
find和findIndex
find:用于找出第一个符合条件的数组元素。找不到则是 undefined 。注意,它是不会返回多个,只找一个,找到了就返回。如果你要把所有的满足条件的数组元素素都找出来,你应该用filter()
let arr=[1,2,3];
arr.find(item=>item>2);//3
复制代码
findIndex:返回第一个符合条件的数组元素的索引。找不到则是-1;
let arr=[1,2,3];
arr.find(item=>item>2);//2
复制代码
七、对象扩展
对象中的简洁表达
ES6 允许直接写入变量和函数,作为对象的属性和方法。 直接写变量时,属性名为变量名, 属性值为变量的值
let a=1;
let obj={a};
//等同于
let obj={a:a}
复制代码
方法也可以简写
let obj={
f(){
return "hello";
}
};
//等同于
let obj={
f:function(){
return "hello";
}
};
复制代码
Object.assign
Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。
Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);
console.log(target); // {a:1, b:2, c:3}
复制代码
注意细节:
第一个参数是目标对象,assign这个方法把其它的参数中的属性全部加在第一个参数身上。
第一个参数在属性复制过程中,可以被修改,如果有相名属性,后面的会覆盖前面的属性。
assign这个方法的返回值就是第一个参数的引用,也就是返回了第一个参数。
assign这个方法会把原型上面的发展也拷贝了。
assign不能拷贝继承过来的属性。
assign也不拷贝不可枚举的属性。
属性相关的方法
Obect.getOwnProertyDescriptor() 获取一个对象中某个属性的详细信息。
Object.defineProperty() 精细化设置一个对象的属性
Object.values() 获取对象的值,放到数组中
Object.keys() 获取对象自身可枚举的属性
Object.getOwnPropertyNames() : 获取对象自身的全部属性名