在之前的内容学习中,已经学会了基础的 DOM操作 和 BOM操作 ,同时也认识了 对象 、函数 、事件 的基本概念和用法,有兴趣的小伙伴可以❤️ 订阅APIs专栏免费学习 ❤️哟;那么接下来就是会结合目前市面上最流行的 ES6 对这些 基础的JS 进行更细化的学习;
说到 ES6 ,我想大家应该都有所耳闻;其实,它就是在2015年6月份迎来的 ECMAScript标准的第六版 的简称,之前的 ES5 都已经可以追溯到2009年了。厚积薄发的ES6可以称得上是内容变化最大的一个版本,它提供了许多的新语法和新特性,在很大程度上帮助开发者们处理更为复杂的业务逻辑,并且还能有效的 增强代码的可读性,减少代码的错误率;那么接下来本专栏 ES6基础学习 主要介绍的就是耳熟能详的 Promise 、箭头函数 、模板字符串 、以及 let 和 解构,当然也包括陌生的 代理、反射 、迭代器 和 生成器 等,欢迎大家订阅关注啦❤️❤️
那么今天主要会学习的内容是:
一、let和const
二、作用域
三、闭包
四、预解析
五、参数
六、箭头函数
在 ES6 之前的版本中,用于声明变量的关键字只有var
,并且没有块作用域,只有函数作用域和全局作用域,但是在 ES6 中由于提出了let
和const
,就彻底改变了以往的局面;它们不仅可以用于声明变量,还可以将变量绑定到当前所处在的任意作用域中,如此一来就形成了块作用域。因此,可简单的了解到let
和const
这两关键字与var大体的区别:
当然,这里也会细讲let
和const
:
其实,对于let
可以理解为是var
的升级版本,摒弃和纠正了var
的一些导致代码混乱的特性,从而使代码的逻辑更清晰,可维护性更高;
特性一:其无法实现变量提升;
代码样例:
{
let inner = true
console.log(inner) //true
}
console.log(inner) //抛出未定义的引用错误
特性二:存在临时死区;
临时死区:也叫暂时性死区,英文简写为 TDZ ;用let
和const
声明的变量,在声明之前是都会被放到 TDZ 中的,如果对于这些变量未赋值便访问的话,就会产生运行错误;
特性三:不允许重复声明;
当然,这里有一个前置条件:就是只有在相同的作用域时,才不允许同一个变量的重复声明;,这完全是因为 ES6 引入了一个重复声明的检查机制,促使着避免项目开发的过程中存在的同名变量影响代码逻辑的情况;
特性四:不覆盖全局变量;
在使用var
在全局作用域中声明变量的时候,该变量不但会成为全局变量,而且还会成为全局对象,而在ES6中,针对这种情况影响函数封装导致不利于代码模块化的问题,规定了使用let
可将全局变量和全局对象断开练习;
代码样例:
var global = true
var Math = true
console.log(window.global)// true
console.log(window.Math)// true
let whole = true
let Math = true
console.log(window.whole)//undefined
console.log(window.Math)//Math对象
对于const
来说,它不但具有let所具有的四大特性,它自己本身也有一个很重要的特性:声明常量 ;
不过,此处需要强调的一点就是,const
限制的其实是变量和内存地址之间的绑定,也就是说:
⭐注意:
const
在声明时必须初始化(即赋值),并且在设定后,其值无法再改变;
基础概念: 作用域(scope)规定了变量能够被访问的 “范围” ,离开了这个 “范围” ,变量便不能被访问了,作用域通常也被分为 全局作用域 和 局部作用域 ;
其中,局部作用域 又分为 函数作用域 和 块作用域,具体如图所示:
而这里学习作用域的主要目的是:了解作用域对程序执行的影响及作用域链的查找机制
基础概念: 当打开浏览器加载 HTML 页面的时候,浏览器首先会提供一个供全局JS代码执行的环境 这个环境就被称为 全局作用域,也就是说script
标签和 .js
文件的【最外层】就是所谓的全局作用域;
代码样例:
<script>
// 此处是全局
function sayHi() {
// 此处为局部
}
// 此处为全局
script>
说明:
window
对象动态添加的属性默认也是全局的(了解即可,不推荐操作);特点: 函数每次执行都会开辟新的内存空间,当函数执行完毕之后,就会关闭这块空间,并且里面的一些变量都会销毁;所以,在函数内部声明的变量只能在函数内部被访问,外部无法直接访问;
代码样例:
<script>
// 声明 counter 函数
function counter(x, y) {
// 局部作用域
// 函数内部声明的变量,为局部变量
let s = x + y;
console.log(s); // 18
}
// 调用 counter 函数
counter(10, 8);
// 访问变量 s
console.log(s); // 报错
script>
说明:
这是在 ES6 中新加入的一个概念,常被理解为是在 JavaScript 中使用 {}
包裹范围区域,这其中的代码也被称为 代码块,代码块内部声明的变量外部将【有可能】无法被访问;
⭐注意:这里标注的【有可能】是因为:在使用
var
声明变量时,是会被提升为全局变量的,而使用let
声明变量时才具有块级作用域的特性;
代码样例:
<script>
{
// age 只能在该代码块中被访问
let age = 18;
console.log(age); // 正常
}
// 超出了 age 的作用域
console.log(age); // 报错
script>
当然,JavaScript 中除了 变量 外还有 常量 ,常量与变量本质的区别是 【常量必须要有值且不允许被重新赋值】 ,常量值为对象时其属性和方法允许重新赋值,这里常用到声明常量的关键词是:const
代码样例:
<script>
// 声明常量,必须要有值
const version = '1.0.0';
// 不能重新赋值
version = '1.0.1';//报错
// 常量值为对象类型
const user = {
name: '小明',
age: 18
}
// 不能重新赋值
user = {};
// 属性和方法允许被修改
user.name = '小小明';
user.gender = '男';
script>
说明:
let
声明的变量会产生块作用域,var
不会产生块作用域;var
和let
都可以只定义不赋值【拓展:对象为空 是返回null
,变量为空 返回undefined
】const
声明的常量也会产生块作用域;const
定义的常量不允许更改值;let
或 const
,不推荐使用var
;⭐注意:开发中
let
和const
经常不加区分的使用,如果担心某个值会不小被修改时,则只能使用const
声明成常量
基础概念: 本质上是底层的变量查找机制,在函数被执行时,会优先查找当前函数作用域中所要查找的变量,如果当前作用域查找不到则会依次逐级查找 父级作用域 直到全局作用域;
代码样例:
<script>
// 全局作用域
let a = 1;
let b = 2;
// 局部作用域
function f() {
let c;
// 局部作用域
function g() {
let d = 'yo';
}
}
script>
由代码可知:函数内部允许创建新的函数,f
函数内部创建的新函数 g
,会产生新的函数作用域,至此函数作用域产生了 嵌套的关系 ;这种由父子关系的作用域关联在一起形成了链状的结构,便是作用域链这个名字的由来;
说明:
⭐注意:作用域链的主要作用就是提供查找变量的机制;
基础概念: 闭包是一种比较特殊的 函数,使用闭包能够访问函数作用域中的变量;例如递归函数就是闭包;
简单理解:闭包就是一个作用域能够有权访问另外一个作用域的局部变量;
从代码形式上理解闭包,其实就是子函数能够访问父函数的变量,并且返回子函数;
代码样例:
<script>
function foo() {
let i = 0;
// 函数内部分函数
function bar() {
console.log(++i);
}
// 将函数做为返回值
return bar;
}
// fn 即为闭包函数
let fn = foo();
fn(); // 1
script>
说明:
⭐注意:回调函数也能访问函数内部的局部变量
基础概念: 在代码执行之前,先要解析整个代码,提取变量或者函数之后再执行代码,它可以不用遵循先定义后执行的规则;
通常,任何一个作用域在执行代码之前都需要先进行预解析这个步骤;在预解析的过程中,通常也会由于变量和函数的存在,被分为两类预解析过程:变量提升 和 函数提升 ;
基础概念: 变量提升其实是 JavaScript 中比较【奇怪】的现象,它是允许在变量声明之前被访问的,也可被称为【变量预解析】;一般情况下仅适用于var
声明的变量;
具体过程:
代码样例:
<script>
// 访问变量 str
console.log(str + ' world!');//返回值为:undefined world!
// 声明变量 str
var str = 'hello ';
script>
说明:
undefined
;let
声明的变量不存在变量提升,推荐使用 let
【也有认为具有提升但是不赋值不能使用】;⭐注意:之所以认为
let
具有提升但是不赋值不能使用的原因是什么?
let
声明的变量在没有初始化之前不能使用,因为此时的变量处于一个 死区 ,不可被使用,只有被赋值之后才能被使用;
基础概念: 函数提升与变量提升比较类似,是指函数在声明之前即可被调用,通常也被称为【函数预解析】;
代码样例:
<script>
// 调用函数
foo();
// 声明函数
function foo() {
console.log('声明之前即被调用...');
}
// 不存在提升现象
bar();
var bar = function () {
console.log('函数表达式不存在提升现象...');
}
script>
说明:
参数通常被使用在函数当中,在函数参数的使用细节里,能够提升函数应用的灵活度,这里主要也含有 形参 、实参 、动态参数 、以及 剩余参数 的概念;
首先对于 形参 和 实参 我想小伙伴应该都不陌生,形参通常在函数定义的时候使用,而实参往往都在函数调用的时候使用;
对于形参而言,也相当于局部变量,通常在没有接受实参的情况下,形参默认是undefined
,但是形参是可以存在默认值的;
代码样例:
//这里的形参被赋了默认值
function getSum (num1 = 0, num2 = 0) {
let he = num1 + num2;
console.log(he);
}
//实参
getSum(6, 3);
说明:
undefined
;基础概念: 在函数传递参数时,实参的个数不固定的情况下,这种参数就被称为动态参数;
那么面对参数无法固定的情况,该如何实现参数的传递呢?
这里就需要用到函数内部的一个 特殊对象 ——【arguments
】,它是函数内部内置的伪数组变量,它包含了调用函数时传入的所有实参;
代码样例:
<script>
// 求和函数,计算所有参数的和
function sum() {
// console.log(arguments);
let s = 0;
for(let i = 0; i < arguments.length; i++) {
s += arguments[i];
}
console.log(s);
}
// 调用求和函数
sum(5, 10); // 两个参数
sum(1, 2, 4); // 两个参数
script>
说明:
arguments
是一个伪数组;arguments
的作用是动态获取函数的实参;⭐注意:在传参的过程中,如果有不想传的参数,可以直接用
undefined
的替代即可;
基础概念: 剩余参数也叫做 rest参数 ,通常的写法是...
代码样例:
<script>
function config(baseURL, ...other) {
console.log(baseURL);
// other 是真数组,动态获取实参
console.log(other);
}
// 调用函数
config('http://baidu.com', 'get', 'json');
script>
说明:
...
是语法符号,置于最末函数形参之前,用于获取多余的实参;...
获取的剩余实参;基础概念: 箭头函数是一种声明函数的简洁语法,它与普通函数并无本质的区别,差异性更多体现在语法格式上;
基础语法结构:
//箭头函数的定义
let 变量名 = ( n个参数 ) => { 函数体 }
//调用
变量名()
场景的应用场景:涉及到 回调函数 ,基本上都可以使用箭头函数;例如定时器、遍历数组的forEach()
;
当然,箭头函数也有其他形式的写法,遇见了得需要认识:
()
,代码样式如下:let 变量名 = 一个参数 => { 函数体 }
{}
,并自动做为返回值被返回,代码样式如下:let 变量名 = 一个参数 => 一行代码的函数体
说明:
this
指向上级作用域的this
,所有如果函数中用到this
,不建议使用箭头函数;要知道,函数中的this
指向调用者(事件源),默认的function
是window
调用的;arguments
,只能使用 ...
动态获取实参;今天是学习 ES6 的第一天,内容还是挺多的,使用练习和理解极为重要,今天所总结出来的所有知识,希望对大家有用,同时也希望这篇文章可以有一个好的展现量和得到更多人的支持,谢谢每一位浏览文章的人,要相信小柴码文,必是好文,欢迎各位 点赞+收藏+关注 啦! ! !
有兴趣的小伙伴们可以回顾之前所学习的Web APIs基础学习的内容,后续即将更新前端开发的学习目标。感谢关注和支持,让我们一起成长!
有兴趣可回顾一下JavaScript基础学习的文章内容,再结合之前所介绍的CSS基础学习以及HTML基础学习,大脑里的内容会更加丰富而充实的,毕竟综合性复习和学习是更会加深印象的哟!!!