let和const和var的区别
let在if,for中都有自己的作用域,而var 没有,一般情况都用let来定义不用var
<script>
for(var i = 0; i < 5; i++){
console.log(i);
}
console.log("循环外:" + i);
for(let j = 0; j < 5; j++){
console.log(j);
}
console.log("循环外:" + j);
</script>
结果:
const定义常量:一般用于定义标识符,定义过以后就不能被修改,但是里面的属性可以修改或者添加
const obj={
name:'张三',
age:18,
}
obj.name='李四'
字符串扩展
ES6新增字符串扩展
- includes(“xxx”):返回布尔值,表示是否包含xxx
- startsWith(“xxx”):返回布尔值,表示是否以xxx开头
- endsWith(“xxx”):返回布尔值,表示是否以xxx结尾
<script>
let str='hello 你是我的小宝宝'
console.log(str.includes("小宝"))//true
console.log(str.startsWith("he"))//true
console.log(str.endsWith("宝宝"))//true
console.log(str.endsWith("小"))//false
</script>
模板字面量
在ES6之前,将字符串连接到一起的方法是+或者concat()方法,如
模板字面量本质上是包含嵌入式表达式的字符串字面量.
模板字面量用倒引号 ( `` )(而不是单引号 ( ‘’ ) 或双引号( “” ))表示,可以包含用 ${expression} 表示的占位符
<script>
let str='你好'
const obj={
name:'张三',
age:'19'
}
//字符串拼接方式
let results=str + '我是' + obj.name
console.log(results)
//模板字面量
let results1=`${str}我的年龄是${obj.age}岁`
console.log(results1)
</script>
解构赋值
在ES6中,可以使用解构从数组和对象提取值并赋值给独特的变量
解构数组的值:
const array = ['mdm',19,'ddd'];
const [x, y, z] = array;
console.log(x, y, z);// mdm 19 ddd
//[]表示被解构的数组, x,y,z表示要将数组中的值存储在其中的变量, 在解构数组是, 还可以忽略值, 例如const[x,,z]=point,忽略y坐标.
const [a, , c] = array;
console.log(a,c)//mdm ddd
解构对象的值:
const person = {
type: 'quartz',
color: 'rose',
karat: 21.29
};
const {type, color, karat} = person;
console.log(type, color, karat);// quartz rose ["ss", 19, "cd"]
// 如果想用其他变量接收,需要指定别名
const {type:n} = person;
console.log(n);// quartz
对象字面量简写
使用和所分配的变量名称相同的名称初始化对象时如果属性名称和所分配的变量名称一样,那么就可以从对象属性中删掉这些重复的变量名称。
let type = 'quartz';
let color = 'rose';
let carat = 21.29;
let gemstone = {
type,
color,
carat,
};
console.log(gemstone);//
{carat: 21.29
color: "rose"
type: "quartz"}
for … of
for…of循环是最新添加到 JavaScript 循环系列中的循环。
它结合了其兄弟循环形式 for 循环和 for…in 循环的优势,可以循环任何可迭代(也就是遵守可迭代协议)类型的数据。默认情况下,包含以下数据类型:String、Array、Map 和 Set,注意不包含 Object 数据类型(即 {})。默认情况下,对象不可迭代。
for循环
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (let i = 0; i < digits.length; i++) {
console.log(digits[i]);
}
for 循环的最大缺点是需要跟踪计数器和退出条件。 虽然 for 循环在循环数组时的确具有优势,但是某些数据结构不是数组,因此并非始终适合使用 loop 循环。
for…in循环
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (const index in digits) {
console.log(digits[index]);
}
依然需要使用 index 来访问数组的值
forEach 循环 是另一种形式的 JavaScript 循环。但是,forEach() 实际上是数组方法,因此只能用在数组中。也无法停止或退出 forEach 循环。如果希望你的循环中出现这种行为,则需要使用基本的 for 循环。
for…of循环
for…of 循环用于循环访问任何可迭代的数据类型。
for…of 循环的编写方式和 for…in 循环的基本一样,只是将 in 替换为 of,可以忽略索引。
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (const digit of digits) {
console.log(digit);
}
建议使用复数对象名称来表示多个值的集合。这样,循环该集合时,可以使用名称的单数版本来表示集合中的单个值。例如,for (const button of buttons) {…}。
for…of 循环还具有其他优势,解决了 for 和 for…in 循环的不足之处。你可以随时停止或退出 for…of 循环。
for (const digit of digits) {
if (digit % 2 === 0) {
continue;
}
console.log(digit);
}
函数优化
在ES6之前,无法给一个函数参数设置默认值,只能采用变通写法:
<script>
如果没有给参数b传值,则b=1
function add(a,b){
b=b || 1
return a+b
}
console.log(add(8))//9
console.log(add(8,9))//17
// 使用ES6
function add1(a,b=2){
return a + b
}
console.log(add1(1))//3
console.log(add1(1,4))//5
</script>
箭头函数
- 一个参数时:
let print = function (obj){ console.log(obj); } // 简写为: let print2 = obj => console.log(obj);
- 多个参数时
let sum = function(a,b){
return a + b;
}
// 简写为:
let sum2 = (a,b) => a + b;
- 没有参数时
// 没有参数时,需要用()进行占位,代表参数部分
let hello = function(){
console.log("Hello ...")
}
// 简写为:
let hello2 = () => console.log("Hello ...")
- 当有多行代码时,可以使用{ }括起来
let sum3 = (a.b) =>{
return a+b;
}
let hello3 = () =>{
console.log("Hello");
console.log("World");
};
hello3();
- 箭头函数结合解构表达式
var hi = ({name}) => console.log("hello," + name);
hi(person);
高阶函数filter,map,reduce
filter函数过滤器的使用
filter中的回调函数有一个要求,就是必须返回一个boolean值,它会把满足条件的重新组成一个新数组,你只需要定义一个新数组来接受它即可
boolean值为true时候,函数内部会自动将这次回调的n加入新的数组中,为false的时候,函数内部会过滤掉这次的n
const array=[10,30,3,45,3,23,33]
let newArray= array.filter(n => n < 30)
console.log(newArray)
map函数使用
map()
方法定义在JavaScript的Array
中,它返回一个新的数组,数组中的元素为原始数组调用函数处理后的值。
map()
不会对空数组进行检测map()
不会改变原始数组
let nums=[1,2,4,2,5,3]
let newNums=nums.map(item => item * item)
console.log(newNums)//[1, 4, 16, 4, 25, 9
reduce函数的使用
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。对空数组是不会执行回调函数的。
- 计算数据总和
let nums=[1,2,4,2,5,3]
let newNums1= nums.reduce((total,num) => total += num, 0);
console.log(newNums1)
- 合并二维数组
let red = [[0, 1], [2, 3], [4, 5]].reduce((a,b) => {
return a.concat(b);
}, []);
console.log(red)//[0, 1, 2, 3, 4, 5]
- 统计一个数组中有多少个不重复的单词或者长度
//不用reduce的方法
let arr = ["apple","orange","apple","orange","pear","orange"];
function getWordCnt(){
var obj = {};
for(var i= 0, l = arr.length; i< l; i++){
var item = arr[i];
obj[item] = (obj[item] +1 ) || 1;
}
return obj;
}
console.log(getWordCnt());// {apple: 2, orange: 3, pear: 1}
使用reduce
let arr = ["apple","orange","apple","orange","pear","orange"];
function getWordCnt(){
return arr.reduce((prev,next) => {
prev[next] = (prev[next] + 1) || 1;
return prev;
},{});
}
console.log(getWordCnt());// {apple: 2, orange: 3, pear: 1}
运算符扩展
onsole.log(...[1,2,3]); // 1 2 3
console.log(1,...[2,3,4],5); // 1 2 3 4 5
function add(x,y) {
return x+y;
}
const number = [1, 2];
console.log(add(...number)); // 3
let arr = [...[1,2,3],...[4,5,6]];
console.log(arr); //[1,2,3,4,5,6]
const [first,...rest] = [1,2,3,4,5,6];
console.log(first,rest); // 1 [2,3,4,5,6]
console.log([..."hello"]); // ["h","e","l","l","o"]
剩余参数
使用展开运算符将数组展开为多个元素, 使用剩余参数可以将多个元素绑定到一个数组中.
剩余参数也用三个连续的点 ( … ) 表示,使你能够将不定数量的元素表示为数组.
用途1: 将变量赋数组值时:
const order = [20.17, 18.67, 1.50, "cheese", "eggs", "milk", "bread"];
const [total,aa, ...items] = order;
console.log(total,aa, items);//20.17 18.67 [1.5, "cheese", "eggs", "milk", "bread"]
用途2: 可变参数函数
对于参数不固定的函数,ES6之前是使用参数对象(arguments)处理:
function sum() {
let total = 0;
for(const argument of arguments) {
total += argument;
}
return total;
}
在ES6中使用剩余参数运算符则更为简洁,可读性提高:
function sum(...nums) {
let total = 0;
for(const num of nums) {
total += num;
}
return total;
}
运算符扩展
扩展运算符(spread)是三个点(…),将一个数组转为用逗号分隔的参数序列。
用法:
console.log(...[1,2,3]); // 1 2 3
console.log(1,...[2,3,4],5); // 1 2 3 4 5
function add(x,y) {
return x+y;
}
const number = [1, 2];
console.log(add(...number)); // 3
let arr = [...[1,2,3],...[4,5,6]];
console.log(arr); //[1,2,3,4,5,6]
const [first,...rest] = [1,2,3,4,5,6];
console.log(first,rest); // 1 [2,3,4,5,6]
console.log([..."hello"]); // ["h","e","l","l","o"]
Promise函数
所谓Promise,简单来说就是容器,里面保存着某个未来才会结束的事件(通常为异步操作)的结果。从语法上说,Promise是一个对象,它可以获取异步操作的消息。Promise提供统一的API,各种异步操作都可以用这样的方式进行处理。
可以通过Promise的构造函数来创建Promise对象,并在内部封装一个异步执行的结果。
new Promise((resolve,reject)=>{
//执行异步操作
setTimeout(()=>{
resolve('aaa')
},1000)
}).then(res =>{
// 自己处理10行代码
console.log(res)
}).catch(err => {
console.log(err)
})
Promise的all方法使用
有两个异步请求,我需要等待这两个都请求完成再执行下一个函数,但是如果我直接用ajax就无法知道哪个先请求完成,需要写判断,那么我们此时就可以用Promise的all函数
Promise.all([
new Promise((resolve, reject) => {
// 用定时器模拟异步请求
setTimeout(() => {
resolve({name:'why',age:18})
},2000)
}),
new Promise((resolve, reject) => {
// 用定时器模拟异步请求
setTimeout(() => {
resolve({name:'zs',age:20})
},5000)
}),
]).then(results => {
console.log(results)
})
Set和Map
ES6提供了Set和Map的数据结构。
Set
Set本质与数组类似。不同于Set中只能保存不同的元素,如果元素相同会被忽略。和Java中的Set集合非常相似。
//构造函数:
let set2 = new Set([1,2,3,4,5]) // [1,2,3,4,5]
// 添加,元素内容不可重复,重复会被忽略
set.add()
// 清空
set.clear()
// 删除指定元素,删除的是元素内容,而不是下标
set.delete(value)
// 判断指定元素是否存在
set.has(value)
// 遍历
set.forEach(function(){})
// 元素个数
set.size
Map
Map本质是与Object类似的结构。不同在于Object强制规定key值只能是字符串。而Map对象的key可以是任意对象:
- object是<String, Object>集合
- map是<Object, Object>集合
const map = new Map([
['key1','value1'],
['key2','value2']
]);
console.log(map)//{'key1'=>'value1','key2'=>'value2'}
// 或者接收一个set
const set = new Set([
['key3','value3'],
['key4','value4']
]);
console.log(set)//{['key3','value3'],['key4','value4']}
const map1 = new Map(map);
console.log(map1)//{'key1'=>'value1','key2'=>'value2'}
const map2 = new Map(set);
console.log(map2)//{'key3'=>'value3','key4'=>'value4'}
map.set('key','value')//{"key1" => "value1", "key2" => "value2", "key" => "value"}
map.delete('key')//{"key1" => "value1", "key2" => "value2"}
map.has('key')
map.forEach(function(key,value){})
console.log(map.keys(),map.values())//{"key1", "key2"} ,{"value1", "value2"}
map.size
map.values()
map.entries()
for(let key of map.keys()){
console.log(key);
}
console.log(...map.values())//value1 value2
class(类)的基本语法
JavaScript的传统方法是通过构造函数定义并生成对象。ES6中引入了class的概念,通过class关键字自定义类。
<script>
class User{
// 构造函数
constructor(name,age=20) {
this.name=name;
this.age=age;
}
// 定义方法
sayHello(){
return `hello${this.name}`
}
// 静态方法
static isAdult(age){
if(age >= 18){
return `成年${age}`
}
return "未成年"+age
}
}
let user = new User("Topm",23)
console.log(user.sayHello())
//静态方法需要使用类来调用
console.log(User.isAdult(18))
</script>
类的继承
// 类的继承
class Jerry extends User{
constructor() {
super("jerry",17)
this.address="上海"
}
}
let jerry=new Jerry()
console.log(jerry)
console.log(jerry.sayHello());
// 静态方法需要使用类来调用
console.log(Jerry.isAdult(jerry.age))
Generator函数
generator是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。
Generator函数有两个特征
- function命令与函数名之间有一个*****号
- 函数体内部使用yield语句定义不同的内部状态
用法:
script type="text/javascript">
function * hello() {
yield "hello";
yield "world";
return "over"
}
let hi = hello();
console.log(hi.next());//{done: false,value: "hello"}
console.log(hi.next());//{done: false,value: "world"}
console.log(hi.next());//{done: false,value: "over"}
console.log(hi.next());//{done: true,value: "undefined"}
</script>
可以看到,通过hello()返回的hi对象,每调用一次next()方法返回一个对象,该对象包含了value值和done状态。知道遇到return关键字或者函数执行完毕,这个时候返回的done状态为true,表示已经执行完毕。
参考文档:
ES6新特性_BadCoder
ES6新特性