第一章:ES6语法
第一节:ES6的概念
ES 的全称是 ECMAScript , 它是由 ECMA 国际标准化组织,制定的一项脚本语言的标准化规范。
ES6 既是一个历史名词,也是一个泛指,含义是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017 等等,而 ES2015 则是正式名称,特指该年发布的正式版本的语言标准。
第二节:为什么使用ES6
每一次标准的诞生都意味着语言的完善,功能的加强。JavaScript语言本身也有一些令人不满意的地方。
- 变量提升特性增加了程序运行时的不可预测性
- 语法过于松散,实现相同的功能,不同的人可能会写出不同的代码
第三节:新增let变量
1.3.1 let
let声明的变量只在所处于的块级有效。
var b=2;//全局变量
if(1==1){
let a=1;
console.log("块内a值是:",a);//1
console.log("块内b值是:",b);//2
}
console.log("a值是:",a);//ReferenceError: a is not defined.
console.log("b值是:",b);//2
1.3.2 For循环使用let变量
举例1:
for(let i=1;i<=10;i++){
console.log(i);//正常打印
}
console.log(i);// ReferenceError: i is not defined
举例2:
for (let i = 0; i < 3; i++) {//父作用域
let i = 'a'; //子作用域
console.log(i);
}
1.3.3 let不存在变量提升
var 变量 可以在变量声明前使用,多少有点奇怪,为了纠正这个现象,let改变了这个语法。
console.log(a);//undefined
var a=1;
console.log(b);
let b=2;ReferenceError: a is not defined.
总结: var声明的变量会在作用域内变量提升,但赋值不会提升,所以是undefined。而let的声明的变量不会提升,所以抛出语法错误。
1.3.4 let暂时性死区
只要块级作用域内存在let命令,它所声明的变量就“绑定”这个区域,不再受外部的影响。
var a = 1;
if (true) {
a = 2;// ReferenceError
let a = 1;
}
总结:
在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”。该变量在声明之前使用都属于“暂时性死区“。
1.3.5 不允许重复声明
// 报错
function func() {
let a = 10;
var a = 1;
}
function func() {
let a = 10;
let a = 1;
}
function func(arg) {
let arg;
}
func()
// 不报错
function func(arg) {
{
let arg;
}
}
func()
1.3.6 let案例
var arr = [];
for (var i = 0; i < 3; i++) {
arr[i] = function () {
console.log(i);
}
}
当用var和let时下方三个值是?
arr[0]();
arr[1]();
arr[2]();
提示:var声明的变量是全局作用域,每次for循环都会产生一个块级作用域,每个块级作用域都声明了一个let变量,互不干扰。
1.3.7 总结
-- let 关键字用来声明块级变量。
-- 特点就是在{}声明具有块级作用域,var变量无此特点。
-- 防止循环变量编程全局变量。
-- let 关键词无变量提升。
-- let 关键词有暂时性死区的特点。{先声明后使用}
第四节:新增const变量
声明常量,常量就是值(内存地址)不能变化的量。
1.4.1 const 具有块级作用域
var a=1;
if(true){
const a=2;
console.log(a);//2
}
1.4.2 const 声明常量必须赋值
if(true){
const a;
console.log(a);// Missing initializer in const declaration
}
1.4.3 常量赋值不能修改
if(true){
const a=2;
a=3;
console.log(a);// Missing initializer in const declaration
}
const person = {};
person.name ="张三";
person.age=18;
person = {};//报错
总结:对象的本身是可变的,所以可以添加属性,但是地址不可改变。
1.4.4 let、const、var 的区别
- 使用 var 声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象
- 使用 let 声明的变量,其作用域为该语句所在的代码块内,不存在变量提升
- 使用 const 声明的是常量,在后面出现的代码中不能再修改该常量的值
- 使用let,const的声明的变量不属性顶层对象,返回undefined。
第五节:解构赋值
ES6中允许从数组中提取值,按照对应位置,对变量赋值,对象也可以实现解构。
1.5.1 数组解构
举例1:
let[a,b,c] = [1,2,3];
console.log(a);//1
console.log(b);//2
console.log(c);//3
本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
举例2:
let [a, [[b], c]] = [1, [[2], 3]];
a// 1
b// 2
c// 3
举例3:
let[a,,c] = [1,2,3]; #省略变量
console.log(a);//1
举例4:
let[a,...c] = [1,2,3];//合并运算符可以展开数组也可合并数组
console.log(c);//[2, 3]
console.log(...c);//2 3
举例5:
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
举例6:
let [x,y='2'] = ['a',undefined];
console.log(y);//如果没有定义,可以用默认值
说明:ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。
1.5.2对象解构
-- 根据key解构
let person = {name:"小帅",age:18};
let {name,age,height} = person;
console.log(name);//小帅
console.log(age);//18
console.log(height);//undefined
说明:对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值,否则解构失败就是undefined。
//根据key更改变量名
let { realname: myname,height=173 } = { realname: '张三', age: 18};
console.log(Myname);//张三
console.log(Myage)//18
console.log(realname)//realname is not defined
console.log(height)//当属性没有的时候支持默认值
说明:对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
1.5.3 字符串解构
let [a,b,c] = "hello";
console.log(a);//h
console.log(b);//2
console.log(c);//l
1.5.4 解构应用
1:变量值交换
let a=1;
let b=2;
[a,b] = [b,a];
console.log(a);
2:函数返回多个值
function myfun(){
return [2,3,4];
}
let [a,b,c] = myfun();
3:函数参数的定义
function myfun([a,b,c]){
console.log(a);
}
myfun([4,5,6]);
第六节:箭头函数
ES6中新增的定义函数的方式。
1.6.1 基础语法
语法:() =>{} // ():函数 =>:必须的语法,指向代码块 {}:代码块
Const myFun = () => { } ;//把函数赋值给myFun
举例:
//原js写法
function myFun(k,v){
return k + v;
}
//es6 写法
const myFun1 = (k,v) => {
return k+v;
}
console.log(myFun(1,2));
console.log(myFun1(10,20));
1.6.2 省略写法
如果形参或者代码块只有一句可以简写:
Const myFun = (k) => {return k+1;} 简写:
Const myFun = k => k +1;
1.6.3 this全局函数
var name = "global this";
function globalTest() {
console.log(this);//window
console.log(this.name);//global this
This.name = “global this change”;
}
globalTest();
说明:globalTest()是全局性的方法,属于全局性调用,因此this就代表全局对象window。
1.6.4 对象方法里的this
如果函数作为对象的方法调用,this指向的是这个上级对象,即调用方法的对象。
const person = {
name:"张三",
age:18,
say:function(){
console.log(this.name);// 张三 这时候的this是person的对象
}
}
person.say();
1.6.5 构造函数对象的this
var name = "golbal";
function person(name,age){
this.name = name,
this.age = age,
this.say = function (){
console.log(this.name,this.age);
}
}
const person1 = new person("张三",18);
const person2 = new person("小帅",19);
person1.say();
person2.say();
说明:构造函数中的this指向新创建的对象本身。
1.6.6 apply/call调用时的this
定义:call(thisObj,Object) 调用一个对象的一个方法,以另一个对象替换当前对象。
说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。
const person1 = {name:"张三",age:18};
var name = "G_张三",age = "G_18";
function myfun1(){
console.log(this.name,this.age);
}
myfun1();//对象是Windows
myfun1.call(person1);//对象改变为person1
说明:两者的区别,myfun.call(person,18,29); myfun.apply(person,[18,29]);
1.6.7 箭头函数中this
箭头函数不绑定this关键字,箭头函数中的this,指向的是函数定义位置的上下文this。
箭头函数中的this指向是它所定义(声明)的位置,可以简单理解成,定义箭头函数中的作用域的this指向谁,它就指向谁。
const obj = { name: '张三'}
function fn () {
console.log(this);//this 指向 是obj对象
return () => {
console.log(this);//this 指向 的是箭头函数定义的位置,那么这个箭头函数定义在fn里面,而这个fn指向是的obj对象,所以这个this也指向是obj对象
}
}
const resFn = fn.call(obj); //{ name: '张三'}
resFn();//{ name: '张三'}
1.6.8 箭头函数应用
练习1:单击按钮2s后改变按钮文字:按钮被点击,在单击按钮改变文字:点击被取消。
var flag = false;
let clickbtn = document.querySelector("#clickbtn");
clickbtn.addEventListener("click",function(){
flag = !flag;
setTimeout(() => {
if(flag){
this.value = '按钮被点击'
this.className='hover' //更换样式
}else{
this.value = '点击被取消'
this.className=’’//更换样式
}