JS中函数的作用域
函数或者变量在哪些地方可以被访问
①函数内部的代码可以访问内部的变量和函数
案例:
function fn() {
var a = 10
console.log(a);
}
fn()//结果:10
②函数内部的代码还可以访问外部部的变量和函数
案例1:
var a = 11
function fn() {
console.log(a);
}
fn()//结果:11
案例2:
function fn() {
a = 100
}
var a = 200;
fn()
console.log(a)//结果:100
解析:调用fn函数后运行,函数内没有声明变量a,就会到函数外寻找变量a
,找到变量a=200,然后运行a=100,外面的a=200变成了a=100,所以程序运行结果为100
③函数外部的代码 不能访问函数内部的变量和函数
案例:
function fn() {
var a = 12
}
console.log(a);
结果:报错
④特例
var obj={name:"karen",say:function fn(){
特例: 这里可以直接使fn()
}}
var obj={name:"karen",say:function(){
这里不可以直接使say()//obj.say()
}}
隐式提升
定义及案例分析助你理解
每一个作用域在运行代码时,会先扫描这个作用域代码中的所有var和function关键字 然后提前声明 再运行代码,接下来看一个小案例助你理解这句话
console.log(a);
console.log(fn);
var a = 20
function fn() {
}
结果:
分析:在运行代码前,会先扫描作用域里的所有var和function关键字,也就是变量a和函数fn,然后将他们提前声明 再运行代码,这是流程
var a;
function fn() {
}
console.log(a);
console.log(fn);
a = 20
①同名标识符提升问题:变量变量同名时
案例助你理解
console.log(a)//undefined
var a=10;
console.log(a)//10
var a=20;
console.log(a)//20
解析:
1.var a;var a;
2.console.log(a)//undefined
3.a=10;
4.console.log(a)//10
a=20;
console.log(a)//20
②同名标识符提升问题:函数和函数同名时
function fn() {
console.log(111)
}
function fn() {
console.log(2222)
}
fn()//2222
隐式提升——综合
案例1与案例2结合理解
function fn(a) {
//隐式操作 var=10
function fm() {
a = a + 1
console.log(a)
}
return fm
}
var f1 = fn(10)
f1()
f1()
/*在这里我们以大括号代表函数的作用域
分析:
/*
fn作用域{
var a=12
return fm
第一次f1调用时作用域{
a = a + 1
console.log(a)//11
}
第一次f1调用时作用域{
a = a + 1
console.log(a)//12
}
}
*/
调用f1时,运行fm函数里的代码,因为fm函数作用域里没有变量a,所以就要到
fn函数的作用域里去找变量a,找到后运行a = a + 1;这时fn函数作用域里的变
量a的值就变为11了 调用f2时,重复调用f1时的步骤,但是要注意f1调用时a的
值已经变为11,
案例2与案例1结合理解
function fn(a) {
function fm() {
a = a + 1
console.log(a)
}
return fm
}
var f1 = fn(10)
f1()
var f2 = fn(10)
f2()
/*
fn作用域{
var a=10
f1调用时作用域{
a = a + 1
console.log(a)//11
}
}
fn作用域{
var a=10
f2调用时作用域{
a = a + 1
console.log(a)//11
}
}
*/
总结
一
函数调用时 相当于函数内部的作用域开始运行代码 那么这个作用域运行代码时会先把一些操作提前执行
顺序就是:
- 1.先把函数内部的形参和局部变量提前声明
- 2.再把实参赋值给形参变量
- 3.然后再把内部的局部函数 提前声明
- 4.再按照代码顺序执行代码(执行的过程中 这个作用域内部有已经隐式提前声明的变量和函数就不再声明了
二
function fn(){
var a=10
return function fm(){console.log(a)}
}
var a=100
fn()()
//虽然第二个小括号是在全局作用域调用运行fm函数 但是fm函数定义的作用域在
//fn内部 因此执行代码的作用域在fn内部
函数调用 运行时的作用域
函数在声明和定义时就有了它的作用域 ,但是函数的调用可能发生在其他作用域,运行代码时 一定是去它声明和定义的作用域执行代码