作用域:
变量(变量名/函数名)的生效使用范围
作用域的分类:
全局作用域(window):一个html页面打开就是一个全局作用域
私有作用域:只有函数生成私有作用域
- 只要你书写了一个函数,就i会生成一个私有作用域
- 一经书写,作用域永生不变
- 作用于上下级关系:书写在哪一个作用域内的函数, 就是哪一个作用域的子级作用域
提供了三个机制:
1.变量定义机制:
-
定义在哪一个作用域下的变量, 就是哪一个作用域的私有变量
-
只能在当前作用域以及后代作用域内使用
// 在全局定义变量 var n1 = 100 console.log(n1) function fn1() { // 在 fn1 私有作用域内定义变量 var n2 = 200 console.log(n1) console.log(n2) function fn2() { // 在 fn2 私有作用域内定义变量 var n3 = 300 console.log(n1) console.log(n2) console.log(n3) } fn2() // console.log(n3) } fn1() // console.log(n2)
2.变量访问机制:
当你需要访问某一个变量的值的时候:
-
首先在自己的作用域内查找,如果有直接使用,停止查找
-
如果没有,自动去父级作用域查找,如果有直接使用,停止查找
-
以此类推,知道全局作用域(window)都没有,那么直接报错, xxx is not defined
// var num = 100 function fn1() { // var num = 200 function fn2() { // var num = 300 console.log(num) } fn2() } fn1() //fn2()这里不能调用fn2因为这是属于fn1私有作用域的私有变量
3.变量赋值机制:
当你需要给某一个变量赋值的时候:
- 首先在自己作用域查找,如果有,直接赋值,停止查找
- 如果没有, 那么自动去到父级作用域查找, 如果有直接赋值, 停止查找
- 以此类推, 直到全局作用域(window) 都没有
- 把这个变量定义为全局变量, 在进行赋值
var num = 100
function fn1(){
// var num = 200
console.log('fn1内修改num1前:',num)
//修改num变量
//fn1内没有私有变量num了,回去父级查找
//修改的就是全局num变量
num = 300
console.log('fn1内修改num后:',num)
}
console.log('fn1调用前:',num)
fn1()
//因为fn1函数调用,fn1内代码执行时,把全局num变量值修改了
console.log('fn1调用后:',num)
function fn1() {
// 访问 num 变量
// 因为此时全局确实没有 num 变量, 这里直接报错
// console.log('fn1 内修改 num 前 : ', num)
// 修改 num 变量
// 自己 fn1 私有作用域内没有. 向上查找
// 发现全局作用域内也没有
// 把这个 num 变量定义为全局变量在进行赋值为 300
// 结论: 因为这句话的执行, 在全局定义了一个叫做 num 的变量
num = 300
// 访问 num 变量
// 结论: 要么 num 被定义为了 fn1 私有变量, 要么这个 num 被定义为了全局变量
console.log('fn1 内修改 num 后 : ', num)
//输出300,确定被定义了
}
// 在 fn1 调用以前直接使用 num 变量, 涉及变量访问机制
// 结论: fn1 调用以前全局是没有 num 这个变量的
// console.log('fn1 调用前 : ', num)
fn1()
// 此时 fn1 已经执行完毕
// 因为 fn1 内的代码, 把 num 定义为了全局变量, 所以这里就可以访问到 num 的是值是 300
console.log('fn1 调用后 : ', num)//输出300,所以定义为全局变量
// 这段代码是在全局作用域下书写
console.log('我在全局作用域下')
// 在全局作用域下定义了一个叫做 fn1 的函数
function fn1() {
// 这里就是全局作用域下的一个 fn1 私有作用域
// 这里是在 fn1 私有作用域内书写的代码
function fn2() {
// 这里就是 fn1 私有作用域的 自己作用域
}
}
// 在全局作用域下定义了一个叫做 fn3 的函数
function fn3() {
// 这里就是全局作用域下的一个 fn3 私有作用域
}
变量的三个形态
什么是变量定义 ?
- 必须要有定义变量的关键字 var / function / …, 或者是函数的形参
var num
var num = 100
function fn() {}
function fn(a, b) {}
什么是变量访问 ?
- 你需要拿到某一个变量所保存的值来使用(运算, 输出, …)
num++
fn()
console.log(aaa)
什么是变量赋值 ?
- 给某一个变量进行赋值操作
- 有赋值符号, 或者函数的实参
\+ num += 10 等价于 num = num + 10
\+ fn(10, 20)
// var num 是变量定义
// num = 10 是变量赋值
// var num = 10
// num + 20 是变量访问
// num = xxx 是变量赋值
// num += 20
// 问题: 为什么没有 var 也算是定义了 ?
num = 10
console.log(num)