持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情
前言
大家好呀,我是L同学。在上篇文章javascript中的作用域中,我们学习了javascript中的作用域,包括局部作用域、全局作用域、作用域链等知识。今天,在这篇文章中,我们继续学习闭包、变量提升和函数等相关知识点。
闭包
闭包让你可以在一个内层函数中访问到其外层函数的作用域的数据。闭包是一种比较特殊的函数,使用闭包能够访问函数作用域中的变量。从代码形式上看闭包是一个做为返回值的函数。闭包本质上仍是函数,只不过不是从函数内部返回的。闭包能够创建外部可访问的隔离作用域,避免全局变量污染。过度使用闭包可能造成内存泄漏。需要注意的是,回调函数也能访问函数内部的局部变量。
<script>
function foo() {
let i = 0;
// 函数内部分函数
function bar() {
console.log(++i);
}
// 将函数做为返回值
return bar;
}
// fn 即为闭包函数
let fn = foo();
fn(); // 1
</script>
变量提升(预解析)
变量提升是 JavaScript 中比较“奇怪”的现象,它允许在变量声明之前即被访问。变量在未声明即被访问时会报语法错误,变量在声明之前即被访问,变量的值为 undefined。let 声明的变量不存在变量提升,所以推荐使用 let。变量提升出现在相同作用域当中,那么我们在实际开发中推荐先声明再访问变量。
<script>
// 访问变量 str
console.log(str + 'world!'); //undefinedworld
// 声明变量 str
var str = 'hello ';
</script>
const
const是在es6中新增的一种定义变量的方式(常量的定义)。
- 使用const声明的常量,不允许重新赋值。
- 使用const声明的常量,必须有初始值。
- const也没有预解析。
- 使用const 声明的常量也会与{}进行绑定,形成块级作用域。
//------ 使用const声明的常量,不允许重新赋值-------
const a = 0
a = 9
console.log(a) //报错
//------ 使用const声明的常量,必须有初始值----------
const age
console.log(age) // 报错
//------ const也没有预解析----------
console.log(address)
const address = '上海'
//------ 使用const 声明的常量也会与{}进行绑定,形成块级作用域----------
if (true) {
const tel = 123456789
}
console.log(tel)
let const var对比
let 和 var 和 const 的区别:
- let 必须先初始化变量,再使用变量,没有预解析的过程,let会与{}绑定,形成块级作用域
- var 会有预解析的过程,提升变量声明,不提升变量赋值
- const 是在es6中新增的一种定义变量的方式(常量的定义)
- 使用const声明的常量,不允许重新赋值
- 使用const声明的常量,必须有初始值
- const也没有预解析
- 使用const 声明的常量也会与{}进行绑定,形成块级作用域
函数
函数提升
函数提升与变量提升比较类似,是指函数在声明之前即可被调用。函数提升能够使函数的声明调用更灵活。函数表达式提升的是变量的声明,函数提升出现在相同作用域当中。
<script>
// 调用函数
foo();
// 声明函数
function foo() {
console.log('声明之前即被调用...');
}
// 不存在提升现象
bar();
var bar = function () {
console.log('函数表达式不存在提升现象...');
}
</script>
函数参数默认值
声明函数时可以为形参赋值即为参数的默认值。如果参数未自定义默认值时,参数的默认值为 undefined。调用函数时没有传入对应实参时,参数的默认值被当做实参传入。
<script>
// 设置参数默认值
function sayHi(name="小明", age=18) {
document.write(`<p>大家好,我叫${name},我今年${age}岁了。</p>`);
}
// 调用函数
sayHi();
sayHi('小红');
sayHi('小刚', 21);
</script>
函数动态参数
arguments 是函数内部内置的伪数组变量,它包含了调用函数时传入的所有实参。 arguments的作用是动态获取函数的实参。需要注意的是,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>
剩余参数
我们可以借助 ... 获取函数的剩余实参。... 是语法符号,它放在最末函数形参之前,用于获取多余的实参。
<script>
function config(baseURL, ...other) {
console.log(baseURL);
// other 是真数组,动态获取实参
console.log(other);
}
// 调用函数
config('http://baidu.com', 'get', 'json');
</script>