Javascript 进阶 2-6 提升

我们先来看看下面这段code的执行结果

http://img2.58codes.com/2024/20121770GvHsVuPNFD.png

当我们执行 doSomthing 的 function 的时候,会发现一开始 mom 是 undefined,继续执行以后 mom 才会 被赋值成字串的 '老妈'。

http://img2.58codes.com/2024/20121770VUvnkC2YT4.png

如果我们执行下面的code,会发生甚么事情呢?

console.log(name);var name = '小美';

答案是

http://img2.58codes.com/2024/20121770VOUKbYyQ1u.png

但如果今天是这样的话

console.log(name2);// var name2 = '小美';

执行结果

http://img2.58codes.com/2024/201217708lkHejSHoC.png

而这个就是我们今天要讨论的主题 -- 提升

http://img2.58codes.com/2024/20121770PZxNdhjxzA.png

首先我们在执行环境之前,还有一个 创造环境 会先被执行。

http://img2.58codes.com/2024/20121770LG7uKPnOD8.png

可以从这张图看到,我们在创造环境的时候,会是先把变数名称放到记忆体中,而记忆体就像是物件的感觉,一个 keyname 对应一个 value 值。

http://img2.58codes.com/2024/20121770RJYZFuBoWk.png

接着就到 执行 的步骤,这时候才会把 值 赋予到记忆体对应的 value 的空间。

http://img2.58codes.com/2024/20121770TvZe3Y78Tk.png

http://img2.58codes.com/2024/20121770DwMePuNaSo.png

在创造环境的时候,把记忆体空间準备好,这个流程我们就叫做 -- 提升

比较不同的是,当使用 函式陈述式 的时候,会在 创造环境 阶段,直接把 keyname 以及 value 都放在记忆体中。

http://img2.58codes.com/2024/20121770k9Mzwga2N2.png

如果由这个例子来看,在创造环境的时,function 的 keyname 以及 value 都已经存在于记忆体中,到执行环境的时候,变数 a 才被赋值。

http://img2.58codes.com/2024/201217706c5AGaKlMt.png

    var a = '1';    console.log(a);

所以这段程式码可以拆解成这样

    // 创造阶段    var a;    // 执行阶段    a = '1';    console.log(a);

再来我们看另一段code

    function call () {        console.log('呼叫');    }    call();

这样的结果很明显会显示 '呼叫' 没问题。

那么改成这样呢

    call();        function call () {        console.log('呼叫');    }

还是一样会显示 '呼叫',因为在 执行阶段 已经将 function 记录在记忆体中,而执行阶段才会执行 call(); 的程式码。

所以 函式陈述式 不管放在哪里都没关係。

那如果是下面的程式码呢?

    call();        var call = function () {        console.log('呼叫');    }

执行结果会是:

http://img2.58codes.com/2024/20121770cGjXhglBLP.png

透过这样的方式(函式表达式)宣言function的话,就会跟变数的过程一样:

    // 创造阶段    var call;    // 执行阶段    call();    call = function () {        console.log('呼叫');    }

那再来看到下面的例子,最后印出来的结果会是甚么呢?

    function call () {        console.log('call 1');    }    var call = function () {        console.log('call 2');    };    call();

答案会是 call 2

因为虽然在 创造环境 的时候, call 的记忆体位置是装着 console.log('call 1'); 。

但在 执行步骤 的时候, call 的记忆体位置被替换成 console.log('call 2'); 。

所以最后的执行结果是 call 2。

就算替换两段 function 的位置,结果还是会一样。

    var call = function () {        console.log('call 2');    };    function call () {        console.log('call 1');    }    call();

最后再来看一个练习题:

    call();        function call () {        if (dog) {            dog = 'shiba';        }    }        var dog = 'husky';    console.log(dog);

这样的执行结果,答案会是甚么呢?

// husky

让我们拆解流程来看看

    // 创造阶段    function call () {        if (dog) {            dog = 'shiba';        }    }    var dog;    // 执行阶段    call();        dog = 'husky';    console.log(dog);

虽然 function 中的判断式有执行,但是这时候变数 dog 是 undefined ,判断是会认为是 false,而不会进 dog = 'shiba'; 的赋值的动作。

最后来到 dog = 'husky';, 所以console.log 出来的就是 husky。

总结:函式陈述式在创造期间就已经“载入”,变数在执行期间赋值。

透过这些实例说明,希望可以让大家更了解 hoisting 的概念。 汪汪


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章