1. 程式人生 > >變量提升,函數提升概念及相關題

變量提升,函數提升概念及相關題

解析 function rip 地方 先後 函數 函數定義 運行 fin

之前總是對變量提升,函數提升一知半解,隨著時間的推移,理解的越來越深刻,接下來就寫一寫,有不對的地方請大家指出來。

1) 變量提升

1. 通過var定義(聲明)的變量, 在定義語句之前就可以訪問到
2. 值: undefined

console.log(a)//undefined
var a = 1111;
console.log(a)//1111

等同於

var a = undefined
console.log(a) //undefined
a = 1111;
console.log(a) //1111

即:變量提升。你在一個作用域任何一個地方聲明變量,都會被提升到作用域開始

2) 函數提升

1. 通過function聲明的函數, 在之前就可以直接調用
2. 值: 函數定義(對象)

例子:

(1)var和函數

<script>
     console.log(a)//function a(){}         
     var a=1;
     console.log(a)//1
     function a(){
   } console.log(a)
//1 </script>

等同於以下代碼:

其過程:變量a先聲明,給a賦值為undefined,後來預編譯函數function a(){}再聲明;輸出a為function a(){} ; 之後給a賦值為1;輸出a為1

<script>
     var
a; a = function a(){} console.log(a)//function a(){} a=1; console.log(a)//1 console.log(a)//1 </script>

(2)var和函數參數

<script>
    var a=8;
    function fn(a,b){ 
        console.log(a)//undefined    當前函數作用域能夠找到a,其值是undefined。 所以不會向外查找
        var a=10;
        console.log(a)
//10 } fn(); </script>

<script>
    function fn(a,b){
        console.log(a)//hello
        var a=10;
        console.log(a)//10
    }
    fn(‘hello‘);
</script>

調用fn的時候傳入參數a,b。 a和b會預編譯賦值undefined,調用fn,傳入"hello", a就被賦值為hello。

函數裏面變量a的默認值就是參數a的值了,輸出a即參數a值。給a賦值為10,輸出a為10。

<script>
    var a=1;
    function fn(a,b){
        console.log(a)//undefined  當前作用域能夠找到a的
        a=2;
        console.log(a)//2
    }
    fn();
</script>

foo();
    function foo(){
        console.log("aaa");
    }

function foo(){
        console.log("aaa");
    }

    foo();

foo();
    var foo = function(){
        console.log("aaa");
    }

報錯運行結果是: foo is not a function

原因是:js解析遇到 foo()時會默認當做函數來解析

var foo;
console.log(foo);  //undefined
foo(); //foo is not a function
 foo = function(){
        console.log("aaa");
    }

如果函數聲明和變量聲明使用同一變量名稱,函數聲明的優先級高於變量

函數,函數參數,var

<script>
    var a=10;
    function fn(a,b){
        console.log(a)//function a(){}   這裏輸出function a(){}, 不是參數a的值
        var a=10;
        console.log(a)//10
        function a(){}
        console.log(a)//10
    }
    fn(15);
</script>

fn裏面有參數a,也有變量a,也有函數a,這種迷惑性更高。其實當你知道三者先後順序之後就不迷惑了

經過測試,我發現:參數a會覆蓋預編譯變量a的默認值,如果有函數,函數會覆蓋參數a的值,就是先後順序而已。

函數形參聲明--->函數聲明---->變量聲明

<script>
    a();//1
    var a = c = function() {
        console.log(2)
    };
    a();//2

    function a() {
        console.log(1)
    }
    a();//2
    (function(b) {
        b();//2    其實就是外部的a
        c();//2     c為什麽是2? 也許有人以為這裏會報錯,其實不會。 原因就在於var b=c=xxx。  c相當於沒有加var 不會預編譯,這裏c直接查找到外部作用域的c
        var b = c = function a() {
            console.log(3)
        }
        b()//3
    })(a);//走到這裏 a已經被賦值表達式重新賦值
    c();//3 由於沒加var 的原因 c已經被立即執行函數內部的賦值表達式改變了值 這裏是3
</script>

console.log(typeof foo); 
console.log(typeof bar); 
console.log(typeof add); //函數的聲明 
function foo(){ alert(‘foo‘); } //命名函數表達式 
var bar = function(){ alert(‘bar‘); }; // 函數表達式-匿名函數 
var add = function(a,b){ return a+b; }

輸出結果為 function undefined undefined

console.log(b);
console.log(b());
var b=1;
function b(){
    return 2;
}

輸出結果為

function b(){
    return 2;
}

2

console.log(a)  // f a() { console.log(a) }
console.log(b) //undefined
function a() {
        console.log(a) 
}
var b = function(){
        console.log(b)
}

變量提升,函數提升概念及相關題