js3---(作用域)

168 阅读4分钟

1.作用域

作用域:标识符(变量和函数名) 在函数的代码块内部和函数的代码块外部能够被访问 函数的代码块内部和函数的代码块外部就是这个标识符的作用域

规则:

1):函数内部的代码可以访问函数内部的标识符,也可以访问函数外部的标识符(副作用)

2):函数外部可以访问函数外部的标识符,但是不能访问函数内部的标识符

总结:

1)通常称函数内部的标识符为局部标识符

2)函数内部为声明的变量为全局变量 如:a=40

案例:

            var total = 0;
	function increment() {
		var total = 0
		total = total + 2
		console.log(total)
	}
	increment()//{var total=0;  total = total + 2}
	increment()//{var total=0;  total = total + 2}

分析: 函数的调用是运行一次代码:每一次调用都会重新执行所有代码,每次调用都会重新声明

var total = 0,因此每次调用的结果为2

2.同名标识符的提升(提前声明)问题

提升:每一个作用域在运行时,js引擎会先把作用域内部的关键字隐式提前扫描 并声明

2.1 函数隐式提升

函数也会隐式提升: 变量值提升声明,函数提升的是整个函数体

            fn()
	function  fn () {
		console.log(666)
	}
            

image.png 分析

1.隐式提升函数 function fn () { console.log(666) }

2.正常运行代码fn()

2.2 案列

案例:

            function fn (a) {
		//var a=外部函数
		//funn fm()
		//fm==>外部函数
		fm=a
		function fm () {
			console.log(124)
		}
		
		fm()
	}		
	var a=function() {
		console.log(123)
	}
	fn(a)
            

image.png

分析:在function fn (a) 内部,先隐式声明外部传入的值var a=外部函数 然后提升函数function fm (),fm=a将fm函数改为a函数,fm()调用时的函数为function() { console.log(123) }

2.3 对象内部的方法不会隐式提升

    function fn () {
		console.log(obj.say)			
		var obj={
			say:function(){}
		}
	}
	fn()
            

image.png

3.同名标识符提升问题

3.1同名标识符提升问题:变量函数同名时

1)变量函数同名时:先变量后函数

2)案列

        console.log(a)
	var a=20
	function  a () {
		console.log(100)
	}		
	console.log(a)
            

image.png

分析

1.先提前声明变量var a

2.再提前声明函数function a () { console.log(100) }

3.console.log(a) a=20 console.log(a)

3.2 同名标识符提升问题:变量和变量同名时

1)变量和变量同名时:先写先提升,后写后提升,运行时就近原则

2)案列:

        console.log(a)//unf
	var a=10;
	console.log(a)//10
	var a=20;		
	console.log(a)//20
            

image.png

分析

1.提升变量var a;var a;

2.console.log(a)//undef

3.a=10;

4.console.log(a)//10

5.a=20;

6.console.log(a)//20

3.3 同名标识符提升问题:函数和函数同名时

1)函数和函数同名时:先写先提升,后写后提升,运行时就近原则

2)案列:

                   function fn () {
			console.log(111)
		}
		function fn () {
			console.log(2222)
		}			
		fn()
                    

image.png 分析

1.提升函数 function fn () { console.log(111) } function fn () { console.log(2222) }

2.fn()调用,就近原则,最后一次声明的fn函数为function fn () { console.log(2222) }, 调用function fn () { console.log(2222) }

4.综合案列及执行流程

4.1 执行流程(口头说法形(形参和变量)实函运)

流程:

1.先隐式提升当前作用域内部的所有形参变量和局部变量 (只是声明提升,不提升赋值)

2.再把实参赋值给形参变量

3.然后执行函数的隐式提前声明

4.再按照代码顺序运行代码

4.2 综合案列

        var a=20
	function fn(a){			
		console.log(a,1)//函数
		a=90
		console.log(a,2)
		var a=100
		console.log(a,3)
		function  a () {
			console.log(6666)
		}
		console.log(a,4)			
	}
	fn(a)
            

image.png

分析

1.提升变量var a;

外部传入的值a=20

提升函数function a () { console.log(6666) }

console.log(a,1),打印函数

2.给变量a赋值a=90

console.log(a,2)//打印90

3.给变量a赋值a=100

console.log(a,3)//打印100

4.a函数没调用 console.log(a,4)//访问变量a打印100

5.函数运行时的作用域

5.1

1)函数运行时的作用域在函数生成(定义和声明)时所在的作用域

2)函数运行时是在写函数代码的地方运行代码,不是在调用代码的地方运行代码

5.2 案列

1)案列1

     function fn(a) {
    	function fm() {
    		a = a + 1
    		console.log(a)
    	}
    	return fm
    }
    var f1=fn(10)
    f1()
    f1()
    

image.png

分析: f1()==>fm()

   {
         var a//提升形参
         a=10///传入实参
        return fm
        a=11//第一次运行后a的值为11
        a=12
        第一次运行
         {
            a = a + 1//a在自己作用域内没有,访问外部a=10  a=10+1
            console.log(a)//11 
             
         }
         
         第二次运行
         {
                             a = a + 1
                             console.log(a)//a在自己作用域内没有,访问外部a=11  a=11+1
                              
         }
        
    }

2) 案列2

        function fn(a) {
    	function fm() {
    		a = a + 1
    		console.log(a)
    	}
    	return fm
    }
    var f1=fn(10)
    f1()			
    var f2=fn(10)
    f2()
    

image.png

分析: var f1=fn(10) f1() ,var f2=fn(10) f2() 表示声明的是两个变量

f1()---fm()

{
         var a//提升形参
         a=10//传入实参
         return fm
        
        {
            
        a = a + 1
        console.log(a)////a在自己作用域内没有,访问外部a=10  a=10+1
        }
     }

f2()---fm()
      {
         var a//提升形参
         a=10//传入实参
         return fm
        
        {
            
        a = a + 1
        console.log(a)////a在自己作用域内没有,访问外部a=10  a=10+1
        }
     }