一、ES5新增的内容
我们说的ES5和ES6其实就是在 js 语法的发展过程中的一个版本而已
1、 数组的相关方法:
1-1. 数组.forEach(function (item, index, arr) {})
1-2. 数组.map(function (item, index, arr) {})
1-3. 数组.filter(function (item, index, arr) {})
1-4. 数组.every(function (item, index, arr) {})
1-5. 数组.some(function (item, index, arr) {})
2、 严格模式
2-1. 使用"use strict"定义严格模式
2-2. 严格模式可以定义在函数的最顶端或程序的最顶端
2-3. 在严格模式下 在变量a 没有声明时 a = 10 ; 这样的赋值会报错,定义两个相同名称的函数参数也会报错
2-4. 严格模式执行效率更高
3、 this指向
每一个函数内部都有一个关键字是 this
【函数内部的 this 只和函数的调用方式有关系,和函数的定义方式没有关系】
3-1.全局定义的函数直接调用时,this=>window
function fn(){
console.log(this); //window
}
fn();
3-2.对象内部的方法调用,this => 调用者(对象)
var obj = {
name:"zhangsan",
age:18,
say:function(){
consoloe.log(this); //方法内部的值是obj
}
}
3-3.事件处理函数,this => 事件源
写法一:
odiv.onclick = function(){
consoloe.log(this); //事件源odiv
}
写法二:
odiv.onclick = fn;
function fn(){
consoloe.log(this); //事件源odiv
}
写法三:
<button onclick = "fn(this)">点我</button>
function fn(a){
console.log(a); //a是实参this,指的是点击的button按钮
}
3-4.定时器内部的this指向winodw
setTimeOut(function(){
consoloe.log(this); //事件源window
},10000)
setInterval(function(){
consoloe.log(this);//事件源window
},10000)
3-5.自调用函数,this => window
(function(){
consoloe.log(this); //window
})()
4、 使用call()、bind()、apply()强行改变this指向
4-1. call()
语法: 函数名.call(要改变的 this 指向,要给函数传递的参数1,要给函数传递的参数2, ...)
注意:会立即执行函数
第一个参数是你要改变的函数内部的 this 指向
第二个参数开始,依次是向函数传递参数
function fn(x,y){
console.log(x);
console.log(y);
console.log(this.age);
}
var obj = {
age: '18'
}
fn(1,2); // 输出的结果是1 2 undefined 原因是fn函数是全局函数,全局函数的 this指向window
需求:想将fn内部的this指向obj,这样的话,就可以使用this.age访问到18
call:
作用:改变this指向的
语法:函数名.call(obj,参数1,参数2...)
注意:1. 会调用函数
2. fn中this指向改变成obj
fn.call(obj,1,2);// 输出的结果是1 2 18
4-2. apply()
语法: 函数名.apply(要改变的 this 指向,[要给函数传递的参数1, 要给函数传递的参数2, ...])
注意:会立即执行函数
第一个参数是你要改变的函数内部的 this 指向
第二个参数是一个数组,数组里面的每一项依次是向函数传递的参数
function fn(x,y){
console.log(x);
console.log(y);
console.log(this.age);
}
var obj = {
age: '18'
}
fn(1,2); // 输出的结果是1 2 undefined 原因是fn函数是全局函数,全局函数的 this指向window
需求:想将fn内部的this指向obj,这样的话,就可以使用this.age访问到18
apply:
作用:改变this指向的
语法:函数名.apply(obj,[参数1,参数2...])
注意:1. 会调用函数
2. fn中this指向改变成obj
fn.apply(obj, [1, 2]) // 输出的结果是1 2 18
4-3. bind()
语法: var newFn = 函数名.bind(要改变的 this 指向,要给函数传递的参数1,要给函数传递的参数2, ...); newFn(传递参数)
返回值:返回一个已经改变了 this 指向的函数
function fn(x,y){
console.log(x);
console.log(y);
console.log(this.age);
}
var obj = {
age: '18'
}
fn(1,2); // 输出的结果是1 2 undefined 原因是fn函数是全局函数,全局函数的 this指向window
bind():
作用:改变this指向的
语法:函数名.bind(obj,参数1,参数2...)
注意
1. 函数返回一个已经改变了this指向的函数
2. fn中this指向改变成obj
var newfn = fn.bind(obj, 1, 2)
newfn();// 输出的结果是1 2 18
【总结】
1. call===>函数名.call(obj,参数...)
2. apply===>函数名.call(obj,[参数...])
3 .bind===>var fn = 函数名.call(obj,参数...);
fn();
二、ES6新增的内容
let和const关键字
1、let/const和var的区别:
1-1. 预解析:var会进行预解析,let/const不会
1. 预解析:var会进行预解析,let/const不会
var命令会发生"变量提升"现象,也就是预解析,即变量可以在声明之前使用,值为undefined。
这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。
// var 的情况
console.log(foo);// 输出undefined
var foo = 2;
// let 的情况
console.log(bar);// 报错 ReferenceError
let bar = 2;
也就意味着被let声明的变量,必须先定义在使用。
1-2. 变量重名:var定义变量可以重名,let/const不允许在同一个作用域下,定义重名变量
2. 变量重名:var定义变量可以重名,let/const不允许在同一个作用域下,定义重名变量
var a = 123;
var a = 123; //可以实现
let b = 123;
let b = 123; //Identifier 'a'has already been declared
1-3. 块级作用域:var没有块级作用域,let/const有
3.块级作用域:var没有块级作用域,let/const有
{
var a = 10;
let b = 123;
}
console.log(a);//输出的结果是10
console.log(b);//输出的结果是 报错:Uncaught ReferenceError: b is not defined
上面代码在代码块之中,
分别用let和var声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量无法被打印,
var声明的变量返回了正确的值。这表明,let声明的变量只在它所在的代码块有效。
再如:
for(let i=0; i<10; i++){
document.write(i);//输出的结果是 0123456789
}
document.write(i);//输出的结果是 报错:Uncaught ReferenceError: b is not defined
上面代码中,计数器i只在for循环体内有效,在循环体外引用就会报错。
2、let和const的区别
let可以被重新赋值, const不可以被重新赋值
const声明即赋值, let可以先声明,后赋值
2-1. let用来声明变量,它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效,类似于C,C++,JAVA局部变量的概念。
2-2. const命令用来声明常量,一旦声明,其值就不能改变。也就是只读变量。
2-3. const的基本用法
const a=10;
a=100; //输出结果 Assignment to constant variable.报错
a.声明常量
const PI = 3.1415;
console.log(PI) // 3.1415
PI = 3; // 输出结果 报错:TypeError: Assignment to constant variable.
b.常量必须初始化
const foo; //输出结果 报错:Missing initializer in const declaration
c.块级作用域
{
const foo = 123;
}
console.log(foo);//输出结果 报错:TypeError: Assignment to constant variable. 与let效果相同
d.声明不提升(const修饰的变量必须先定义后使用)
if (true) {
console.log(MAX);// 输出结果 报错:Uncaught ReferenceError
const MAX = 5;
}
3、字符串新增
3-1. str.includes(元素) 在字符串中判断是否包含某个元素,返回的是布尔值
3-2. str.startsWith(字符串) 判断字符串是否以某个字符串开始,返回布尔值
3-3. str.endsWith(字符串) 判断字符串是否以某个字符串开始,返回布尔值
3-4. str.repeat(n) 让字符串重复n次
4、箭头函数
4.1 ES6 语法中定义函数的一种方式
4.2 函数定义的方式:
2.2.1 声明式 function fn() {}
2.2.2 赋值式 var fn = function () {}
2.2.3 箭头函数(赋值式的一种简化写法) var fn = () => {}
2.3 箭头函数的特点:
2.3.1 当你的形参只有一个的时候, 可以不写小括号
var fn = (a)=>{consloe.log(a)}
//简写
var fn = a=>{consloe.log(a)}
2.3.2 当你的函数体只有一行代码时, 可以省略大括号不写
var fn = (a)=>{consloe.log(a)}
//简写
var fn = a=>consloe.log(a)
2.3.3 当你的函数体只有一行代码并且有return,return都可以不写
var fn = (a,b)=>{return a+b}
//简写
var fn = (a,b)=>a+b
2.3.4 箭头函数内部的this
箭头函数内部不绑定this,箭头函数内的this指向箭头函数所在的上下文环境
三、解构赋值
快速从对象或者数组中获取一些数据,分为解构数组和解构对象
1、解构数组
var arr = [12,43,32,3,32];
console.log(arr[0],arr[1],arr[2],arr[3]); //输出结果为 12 43 32 3 32
var [a,b,c,d,e] = arr;
console.log(a,b,c,d,e);//输出结果为 12 43 32 3 32
【注】解构赋值的语法:var [a,b,c,d,e] = arr;
作用:相当于a,b,c,d,e分别存储的是12,43,32,3,32
2、解构对象
var obj = {name:"zhangsan",age:"18",sex:"男"}
console.log(obj.name,obj.age,obj.sex);//输出结果 zhangsan 18 男
console.log(obj['name'],obj['age'],obj['sex']);//输出结果 zhangsan 18 男
for(let k in obj){
console.log(obj[k]);//只能使用[]语法,因为[]语法是支持变量的
} //输出结果 zhangsan
// 18
// 男
let {name,age,sex} = obj;
console.log(name,age,sex); //输出结果 zhangsan 18 男
【注】解构赋值的语法:let {name,age,sex} = obj;
3、解构赋值的用途
函数只能返回出来一个值,解构赋值可以让函数返回出来多个值
要求:1-100内所有的能被4整除的数字的个数,并且计算数字和
function getCount_Sum(){
var sum = 0;
var count = 0;
for(var i = 1;i<=100;i++){
if (i%4==0) {
count++;
sum+=i;
}
}
return [sum,count];
}
var [sum,count] = getCount_Sum();
console.log(sum); //1300
console.log(count); //25
console.log(getCount_Sum()); // [ 1300,25]
四、展开、合并运算符
1、展开数组
var arr = [12, 34, 45, 2];
console.log(arr[0], arr[1], arr[2], arr[3]); //12 34 45 2
展开:将数组中的元素一一展开,等价于上面的写法
console.log(...arr); //12 34 45 2
2、合并数组
合并: 将传递的实参以数组的形式接收,形参是一个数组形式
function fn(...arr) {
console.log(arr); //[1,2,3,4,5]
var sum = 0;
arr.forEach(item => {
sum += item;
})
console.log(sum); //15
}
fn(1, 2, 3, 4, 5);//arr = [1,2,3,4,5]
五、默认参数
概念:给函数的形参设置一个默认值, 当你没有传递实参的时候, 默认参数会生效
function fn(a = 4, b = 1) {
console.log(a, b)
}
fn(1, 2);//1 2
fn();// 4 1
六、字符串新增语法
1、语法:str.includes('子字符串')
返回值:true/false
作用:判断字符串str是否包含子字符串
2、 语法: str.startsWidth('子字符串substr')
返回值:true/false
作用:判断str是否以substr开始
3、 语法: str.endssWidth('子字符串substr')
返回值:true/false
作用:判断str是否以substr结束
4、 语法:str.repeat(n) :
作用:让字符串重复n次
返回值:重复后的字符串
5、模板字符串
var obj = {
name:"zhangsan",
age:18,
sex:'男'
}
var oP =document.querySelector('p')
oP.innerHTML = `我的姓名是${obj.name},性别是${obj.sex},年龄是${obj.age}`
oP.innerHTML = '我的姓名是'+obj.name+',性别是'+obj.sex+',年龄是'+obj.age;
七、set和map集合
1、set:数据结构,类似于数组
Set:数据结构,类似于数组,但是它的值不会重复(自动去重)
Set的属性:set.size获取元素的长度
Set的方法:set.add(ele) 向Set中添加元素
set.delete(ele) 删除某元素
set.has(ele) 是否包含某个元素,返回布尔值
set.clear() 清空set集合
var set = new Set([1, 12, 3, 12, 1, 3]);
console.log(set.size); //输出set去重后的个数 3
增加一个元素
set.add(18)
console.log(set); //{1, 12, 3, 18}
set.add(12)
console.log(set); //{1, 12, 3, 18}
删除一个元素
set.delete(12)
console.log(set); //{1, 3, 18}
判断是否包含
console.log(set.has(18)); // 返回true
清空
set.clear();
console.log(set); // {size: 0}
数组去重
var arr = [12, 12, 21, 3, 21, 3];
var set = new Set(arr);// 类似于数组,不是数组(就是伪数组)
console.log(set); //{12, 21, 3}
将伪数组转为真正的数组 --->真数组 = Array.from(伪数组)
var zArr = Array.from(set);
console.log(zArr); // [12, 21, 3]
简写:
var arr = [12, 12, 21, 3, 21, 3];
console.log(Array.from(new Set(arr))); // [12, 21, 3]
2、Map:数据结构,类似于对象
Map的属性:map.size获取元素的长度
Map的方法:map.set('key','value') 设置键值对
map.get(key) 获取某元素
map.delete(key) 删除某元素
map.clear() 清空map集合
map.has(key) 对象中是否包含某元素,返回布尔值
var map = new Map();
console.log(map); //Map(0) {size: 0}
map.set('name', 'zhangsan')
map.set('age', '18')
map.set('sex', '男')
console.log(map);//Map(3) {'name' => 'zhangsan', 'age' => '18', 'sex' => '男'}
如果想获取键的值
console.log(map.get('name')); //zhangsan
console.log(map.get('age')); //18
console.log(map.get('sex')); //男
刪除
map.delete('name')
console.log(map);//Map(2) {'age' => '18', 'sex' => '男'}
遍历:map用的是for..of
for (var item of map) {
获取键(item[0])和值(item[1])
console.log(item[0] + '-----' + item[1]); //name-----zhangsan
//age-----18
//sex-----男
}
清空
map.clear();
console.log(map); //Map(0) {size: 0}
八、for..of和for..in的小小总结
1、数组:for.in循环可以遍历数组,遍历的是下标(字符串类型)
for.of可以遍历数组,遍历的是值
var arr = [12, 34, 12, 5, 6]
for (var k in arr) {
console.log(k);//k代表的是字符串形式的下标
// 0 1 2 3 4
}
for (var k of arr) {
console.log(k);// k代表的是数组元素
// 12 34 12 5 6
}
2、对象:for..in循环遍历对象
for..of不可以遍历对象
var obj = { name: 'zhangsan', age: 18 }
for (var k in obj) {
console.log(k + '---' + obj[k]);//name---zhangsan
//age---18
}
// for..of不能遍历对象
for (var k of obj) {
console.log(k); //报错 Uncaught TypeError: obj is not iterable
}
3、map集合:for..of可以遍历map集合
for..in不能遍历map集合
var map = new Map();
map.set('name', 'zhangsan')
map.set('age', '18')
map.set('sex', '男')
console.log(map); //Map(3) {'name' => 'zhangsan', 'age' => '18', 'sex' => '男'}
for (var k of map) {
console.log(k); //['name', 'zhangsan']
// ['age', '18']
// ['sex', '男']
console.log(k[0] + '---' + k[1]); //name---zhangsan
//age---18
//sex---男
}