这是我参与8月更文挑战的第24天,活动详情查看:8月更文挑战
前言
大家好哇,今天我们来谈谈JavaScript中函数的作用域的概念,对于非科班出身的小伙伴而言,这其中的概念还是很容易被搞混的,所以今天我们就来好好谈一下这个问题。
文章目标
先来看一下本文的目标吧,大神请绕道,因为本文基本摘自我刚入行时的笔记哦~
重点
1. 知道词法作用域的规则
2. 知道如何使用字面量形式创建一个对象
3. 知道如何使用构造函数批量的创建对象
4. 熟记new关键字的作用
函数的作用域
函数的作用域的还是比较常用的概念,同时也会涉及到参数生效范围、this的指向等问题。
作用域链
作用域链:当一段js代码中书写完毕之后,就会形成一个作用域链
var num = 0 // 全局变量
function fn(){
var num1 = 1 // fn的局部变量
function fnSon(){
var num2 = 2 // fnSon的局部变量
}
}
上面的代码对应的作用域的图解:
词法作用域规则
什么是词法作用域规则
词法作用域又叫做静态作用域(因为代码书写完毕之后,作用域以及作用域链就形成了)
它规定了js中访问变量的规则
为什么会有词法作用域规则
掌握了词法作用域的规则,才能更清楚的知道代码是如何执行的
面试的过程中,经常会出现词法作用域规则的笔试题
词法作用域有哪些规则:
内部的作用域可以访问外部作用域的变量,但是外部的作用域不可以访问内部作用域的变量
访问变量或者给变量赋值时,如果当前作用域有变量则使用当前作用域的变量,如果没有则顺着作用链往上找,直到全局
内部作用域可以访问外部作用域的变量,如:
var num = 0
function fn(){
console.log(num) // 0 内部作用域可以访问外部作用域的变量
}
fn()
外部作用域不可以访问内部作用域的变量,如:
function fn(){
var num1 = 1
}
fn()
console.log(num1) // 报错: num1 is not defined
当前作用域有,则使用当前作用域的变量,如:
var num = 0
function fn(){
var num = 1
console.log(num) // 1
}
当前作用域没有,则顺着作用链往上找,如:
var num = 0
function fn(){
function fnSon(){
console.log(num) // 0
}
}
词法作用域题目
相信通过上面的了解,你对词法作用域已经有了一个基本的了解,下面我们来做几道题目验证一下。感兴趣的话可以把你的答案贴在评论区哦~
第一题
function fn(){
var a = 1, b = 1, c = 1
}
fn()
console.log(c) //
console.log(b) //
console.log(a) //
第二题
var num = 123
function f1(num) {
console.log(num); //
}
function f2() {
var num = 456
f1(num)
}
f2()
第三题
var a = 1
function fn(){
var a = 2
function fnSon(a){
a = 3
console.log(a) //
}
fnSon()
console.log(a) //
}
console.log(a) //
fn()
console.log(a) //
预解析(变量与函数提升)
预解析:JS引擎 会在 执行js代码之前,扫描一遍所有的代码,会将用var 声明的变量和函数申明提前加载到内存中,就相当于把用var声明变量和函数声明写在了代码的最上面,所以又叫做变量提升和函数提升。
变量提升
如下代码:
console.log(num) // undefined
var num = 2
这段代码可以正常执行,由于预解析,把num变量提前加载到内存中,所以就相当于把var num写在了代码的最上面。即:
var num
console.log(num) // undefined
num = 2
函数提升
注意: 只有函数声明会提升,函数表达式不会提升
fn() // hello world
function fn(){
console.log('hello world')
}
这段代码可以正常执行,由于预解析,把fn函数提前加载到内存中,所以就相当于把fn函数写在了代码的最上面。
如果变量名和函数名冲突的话,那么函数名会覆盖变量名。如:
function fn(){}
var fn = 2
console.log(fn) // 打印的是函数
函数中的代码执行之前也会先进行预解析
function fn(){
console.log(num) // undefined
var num
fnSon()
function fnSon(){
console.log('fnSon里面的代码')
}
}
fn()
这段代码可以正常执行,因为函数内的代码执行之前,也会先进行预解析。
后记
你好哇,我是南极大冰块,一个技术与颜值成正比的前端工程师,崇尚一针见血的搞定前端问题,希望我的博客有帮助到了你。
关注我,前端路途一起走。嘿哈~😛