一.let和const
我们通常用 let 和 const 来声明,let 表示变量、const 表示常量。
1.没有变量提升
console.log(a);
let a = 4;
// a is not defined
复制代码
2.不能重复申明
let a = 4;
let a = 5;
console.log(a);
// Identifier 'a' has already been declared
复制代码
3.具有块级作用域(由花括号包裹的区域)
for(let i = 0; i < 3; i++){
console.log(i); //0 1 2
}
console.log(i);
//i is not defined
复制代码
4.临时失效区(暂时性死区)
JS引擎扫描代码时,如果发现变量声明,用var声明变量时会将声明提升到函数或全局作用域的顶部。但是 let或者const,会将声明关进一个小黑屋也是TDZ(暂时性死区),只有执行到变量声明这句语句时,变量才会从小黑屋被放出来,才能安全使用这个变量。
var tt=123
if(true){
console.log(tt)//tt is not defined
let tt=456;
}
复制代码
一道面试题:
var funcs = []
for (var i = 0; i < 10; i++) {
funcs.push(function() { console.log(i) })
}
funcs.forEach(function(func) {
func()
})
复制代码
结果呢,就是打印十个10,怎样才能打印出0到9呢?我们可以这样改。
const funcs = []
for (let i = 0; i < 10; i++) {
funcs.push(function() {
console.log(i)
})
}
funcs.forEach(func => func())
复制代码
const 声明的变量是常量,意思就是它的值被设置完成后就不能再修改了。 如果 const 的是一个对象,对象所包含的值是可以被修改的。就是对象所指向的地址不能改变,而变量成员是可以修改的。
const tt={name:"wangcai"};
tt.name="xiaoming";
console.log(tt.name)
//xiaoming
复制代码
二.箭头函数
function() 函数的简写表示法,但它不绑定 this。
var object = {
name: "wangcai",
arrowGetName: () => this.name,
regularGetName: function() { return this.name },
arrowGetThis: () => this,
regularGetThis: function() { return this }
}
console.log(this.name)
//
console.log(object.arrowGetName());
//
console.log(object.arrowGetThis());
//window
console.log(this)
//window
console.log(object.regularGetName());
//wangcai
console.log(object.regularGetThis());
//object
复制代码
三.模板字符串
如果使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中。
const t="hello"
console.log(`hh${t}`)
//hhhello
复制代码
console.log(`<div>
hahhah
</div>`)
//<div>
//hahhah
//</div>
复制代码
1.trim
除去字符串空格的。
trim 左右空格都是去掉
trimLeft 左空格去掉
trimRight 右空格去掉
2.repeat
3.includes
var str="abc"
console.log(str.includes("a"))
//true
复制代码
4.startsWith和endsWidth
var str="abc def"
console.log(str.startsWidth("abc"))
//true
console.log(str.endsWidth("def"))
//true
复制代码
5.padStart和padEnd
var str="abc def"
console.log(str.padStart(15,"*"))
//"********abc def"
复制代码
var s=4
console.log(s.toFixed(2))
//4.00
console.log(s.toFixed(2).padStart(5,"0"))
//04.00
复制代码
四.解构赋值
//对象
let people = {
name: 'lux',
age: 20
}
const { name, age } = people
console.log(`${name} --- ${age}`)
//lux---20
//数组
const color = ['red', 'blue']
const [first, second] = color
console.log(first)
//'red'
console.log(second)
//'blue'
复制代码
function f(x, y=12) {
return x + y;
}
console.log(f(3))//15
console.log(f(3,2))//5
复制代码
如果解构不成功,变量的值就等于undefined。如下:
let [foo] = [];
let [bar, foo] = [1];
复制代码
foo的值都会等于undefined。
let [x = 1, y = x] = [];
console.log(x, y)
// x=1; y=1
let [a = 1, b = a] = [2];
console.log(a, b)
// x=2; y=2
let [e = 1, f = e] = [1, 2];
console.log(e, f)
// x=1; y=2
let [t = d, d = 1] = [];
console.log(t, d)
// ReferenceError: d is not defined
复制代码
上面最后一个表达式之所以会报错,是因为x用y做默认值时,y还没有声明。
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
复制代码
类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。
let {length : len} = 'hello';
len // 5
复制代码
五.扩展运算符
let arr=[1,2,3]
let arr2=[...arr]
console.log(arr2)
//[1, 2, 3]
arr[0]=666
console.log(arr2)
//[1, 2, 3]
复制代码
数组的复制---这里是浅拷贝
可以利用扩展运算符,把类数组转成数组
把一个类数组转成数组有如下几种方式:
Array.prototype.slice.call();
Array.from();
[...类数组对象]
//数组
const number = [1,2,3,4,5]
const [first, ...rest] = number
console.log(rest) //2,3,4,5
//对象
const user = {
username: 'lux',
gender: 'female',
age: 19,
address: 'peking'
}
const { username, ...rest } = user
console.log(rest) //{"address": "peking", "age": 19, "gender": "female"
}
复制代码
const first = {
a: 1,
b: 2,
c: 6,
}
const second = {
c: 3,
d: 4
}
const total = { ...first, ...second }
console.log(total) // { a: 1, b: 2, c: 3, d: 4 }
复制代码
有重复的属性名,会覆盖。
六.严格模式
之前学习的JS,语法非常灵活,JS中这个灵活的特性,弊大于利。后来增加了严格模式。使用严格模式的目的:规则,提高编译效率。
怎么去启动严格模式: "use strict"
列举如下几条:
在严格模式下不能使用没有var的变量。
在严格模式下不能8进制的数字。
在严格模式下不能把函数定义在if语句中。
"use strict";
if(true){
function f(){
console.log("f.....")
}
}
f();
//f is not defined
复制代码
在严格模式下函数不能有重名的形参
"use strict";
function f(a,a){
console.log("f.....")
}
f();
// Uncaught SyntaxError: Duplicate parameter name not allowed in this context
复制代码
arguments不会自动反映函数参数的变化
"use strict";
function f(a,b){
console.log(a,b)
// 1 2
console.log(arguments[0],arguments[1])
//1 2
arguments[0]=111
arguments[1]=222
console.log(a,b)
//1 2
console.log(arguments[0],arguments[1])
//111 222
}
f(1,2);
复制代码
不能删除不可删除的属性,否则报错
禁止this指向全局对象
"use strict";
function f(){
console.log(this)
}
f();
//undefined
复制代码
七.set
ES6 提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。Set 本身是一个构造函数,用来生成 Set 数据结构。
放一个数组
var s1=new Set([1,2,3,"true"])
console.log(s1)
//
复制代码
结果为:
放一个对象
使用add()来添加,遍历时,使用for each或者for of
var s1=new Set()
s1.add(1)
s1.add(2)
s1.add(3)
s1.forEach(item=>console.log(item))
//1 2 3
复制代码
set不是数组,是一个像对象的数组,是一个伪数组。Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。
操作方法(用于操作数据)
add(value):添加某个值,返回 Set 结构本身。
delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
has(value):返回一个布尔值,表示该值是否为Set的成员。
clear():清除所有成员,没有返回值。
s.add(1).add(2).add(2);
// 注意2被加入了两次
s.size // 2
s.has(1) // true
s.has(2) // true
s.has(3) // false
s.delete(2);
s.has(2) // false
复制代码
遍历方法(用于遍历成员)
keys() 返回键名的遍历器
values() 返回键值的遍历器
entries() 返回键值对的遍历器
forEach() 使用回调函数遍历每个成员
keys方法、values方法、entries方法返回的都是遍历器对象。由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致。
let set = new Set(['red', 'green', 'blue']);
for (let item of set.keys()) {
console.log(item);
}
// red
// green
// blue
for (let item of set.values()) {
console.log(item);
}
// red
// green
// blue
for (let item of set.entries()) {
console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]
复制代码
八.map
Map 类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content')
m.get(o) // "content"
m.has(o) // true
m.delete(o) // true
m.has(o) // false
复制代码
const map = new Map();
map.set(['a'], 555);
map.get(['a']) // undefined
复制代码
内存地址不一样,所以是两个值,返回undefined。
Map 结构的实例有以下属性和操作方法。
属性
size
size属性返回 Map 结构的成员总数。
const map = new Map();
map.set('foo', true);
map.set('bar', false);
map.size // 2
复制代码
set(key, value)
set方法设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新。
get(key)
get方法读取key对应的键值,如果找不到key,返回undefined。
has(key)
has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。
delete(key)
delete方法删除某个键,返回true。如果删除失败,返回false。
clear()
clear方法清除所有成员,没有返回值。
操作方法
keys():返回键名的遍历器。
values():返回键值的遍历器。
entries():返回所有成员的遍历器。
forEach():遍历 Map 的所有成员。
map的操作方法和set类似,就不上代码啦。
九.class
从形式上,向主流的面向对象的语言靠拢。我们以前都是创建构造器,然后去new构造器,构造器就相当于一个类,在ES6中,就可以使用class来创建对象了。
function Nplayer(name,age,height){
this.name=name;
this.height=height
this.age=age
}
Nplayer.prototype.say=function(){
console.log(`我是${this.name},是NBA球员`)
}
var p1=new Nplayer("库里","30","191")
p1.say();
//我是库里,是NBA球员
复制代码
我们可以用class这样写:
class Nplayer {
constructor(name, age, height) {
this.name = name;
this.height = height
this.age = age
}
say() {
console.log(`我是${this.name},是NBA球员`)
}
}
var p1 = new Nplayer("库里", "30", "191")
p1.say();
//我是库里,是NBA球员
复制代码
使用extends实现继承
使用 extends 关键字来实现继承
在子类中的构造器 constructor 中,必须要显式调用父类的 super 方法,如果不调用,则 this 不可用
//父类
class Nplayer {
constructor(name, age, height) {
this.name = name;
this.height = height
this.age = age
}
say() {
console.log(`我是${this.name},是NBA球员`)
}
}
//子类
class MVP extends Nplayer {
constructor(name, age, height,year) {
super(name,age,height)
this.year = year
}
show() {
console.log(`我是${this.name},是${this.year}的球员`)
}
}
var p1 = new MVP("库里", "30", "191","2018")
p1.show();
//我是库里,是2018的球员
复制代码
类的静态方法 static
直接通过类名来访问的方法就是静态方法。如:Math.abs();这里的 abs()是静态方法。 Array.isArray();isArray()是静态方法, 在方法名前加 static 就可以了。这个就不多说了。
总结
关于es6的新增特性呢,还有很多,这里就不一一列举了,可以自行www.baidu.com,搜索一下,阮一峰,哈哈。