js預(yù)編譯和作用域鏈以及閉包

js中有暗示全局變量:任何變量如果未經(jīng)聲明就賦值,此變量就為全局對(duì)象所有(不管在哪里)。

a = 10;
console.log(window.a) //10

window就是全局的域。一切聲明的全局變量,全是window的屬性。

var a = 123;
console.log(window.a) //123
  • js函數(shù)預(yù)編譯四部曲

預(yù)編譯結(jié)束后執(zhí)行函數(shù):

function test(a){
console.log(a);  //function a(){}

var a = 123

console.log(a); //123

function a(){}

console.log(a); //123

var b = function(){}

console.log(b);//function(){}

function d(){}
}
  • 全局預(yù)編譯三部曲:

    1、生成一個(gè)GO對(duì)象(Global Object)就是window。
    2、找變量聲明,將變量名作為GO屬性名,值為undefined。
    3、找函數(shù)聲明(注意不是函數(shù)表達(dá)式),值賦予函數(shù)體。

知識(shí)點(diǎn): 1、GO發(fā)生在AO前。 2、形參和實(shí)參有映射規(guī)定:形參變,實(shí)參也變。實(shí)參出生有幾個(gè)就幾個(gè),不對(duì)應(yīng)形參個(gè)數(shù)就不映射。3、typeof(NaN) // "Object"

作用域

運(yùn)行期上下文:當(dāng)函數(shù)執(zhí)行前一刻,會(huì)創(chuàng)建一個(gè)稱為執(zhí)行期上下文的內(nèi)部對(duì)象。一個(gè)執(zhí)行期上下文定義了一個(gè)函數(shù)執(zhí)行時(shí)的環(huán)境,函數(shù)每次執(zhí)行時(shí)對(duì)應(yīng)的執(zhí)行上下文都是獨(dú)一無二的,所以多次調(diào)用一個(gè)函數(shù)會(huì)導(dǎo)致創(chuàng)建多個(gè)執(zhí)行上下文,當(dāng)函數(shù)執(zhí)行完畢,它所產(chǎn)生的執(zhí)行上下文被銷毀。
[[scope]]:每個(gè)javascript函數(shù)都是一個(gè)對(duì)象,對(duì)象中有些屬性我們可以訪問,但有些不可以,這些屬性僅供javascript引擎存取,[[scope]]就是其中一個(gè)。
[[scope]]指的就是我們所說的作用域,其中存儲(chǔ)了運(yùn)行期上下文的集合。
作用域鏈:[[scope]]中存儲(chǔ)著執(zhí)行期上下文對(duì)象的集合,這個(gè)集合呈鏈?zhǔn)芥溄?,我們把這種鏈?zhǔn)芥溄咏凶鲎饔糜蜴?。(每個(gè)函數(shù)都有自己的作用域鏈)
查找變量:在哪個(gè)函數(shù)中查找就從這個(gè)函數(shù)作用域鏈的頂端依次向下查找。(在全局定義的函數(shù),它的運(yùn)行期上下文就是全局域)。

function a(){
    function b(){
      var  b = 234;
    }
var a = 123;
b();
}
var glob = 100;
a();

//a函數(shù)被定義時(shí)產(chǎn)生 a.[[scope]] -->  0:GO{}
//a函數(shù)被執(zhí)行時(shí) a.[[scope]] --> 0:AO{}
//                             1:GO{}
//b函數(shù)被定義時(shí) b.[[scope]] --> 0:AO{} a的AO
//                             1:GO{}
//b函數(shù)被執(zhí)行時(shí) b.[[scope]] --> 0:AO{} b的AO
//                             1:AO{} a的AO引用
//                             1:GO{}
a函數(shù)被定義時(shí).png

a函數(shù)執(zhí)行.png

b函數(shù)被定義時(shí).png

b函數(shù)被執(zhí)行時(shí).png

閉包

當(dāng)內(nèi)部的函數(shù)被保存到外部時(shí),將會(huì)生成閉包。閉包會(huì)導(dǎo)致原有作用域鏈不釋放,造成內(nèi)存泄漏。

function a(){
  function b(){
      var bbb = 234;
      consoloe.log(aaa);
  }
var  aaa = 123;
return b;
}
var glob = 100;
var demo = a();
demo();
閉包作用域鏈.png
  • 閉包的作用:
    • 1.實(shí)現(xiàn)公有變量
      • eg:函數(shù)累加器
    • 2.可以做緩存(存儲(chǔ)結(jié)構(gòu))
      • eg:eater
    • 3.可實(shí)現(xiàn)封裝,屬性私有化。
      • eg:Person();
    • 4.模塊化開發(fā),防止污染全局變量
1.就是閉包實(shí)現(xiàn)累加
function add(){
  var count = 0;
  function demo(){
    count ++;
    console.log(count);
  }
return demo;
}
var counter = add();
counter(); //1
counter(); //2

2.可以做緩存(存儲(chǔ)結(jié)構(gòu))
function test(){
  var num = 100;
  function a(){
    num ++;
    console.log(num);
  }
  function b(){
    num --;
    console.log(num);
  }
return [a,b];
}
var myArr = test();
myArr[0](); //101
myArr[1](); //100

function fn(name){
    var _age;
    function setAge(n){
            _age = n;
    }
    function getAge(){
            return _age;
    }
    return{
            name:name,
            setAge:setAge,
            getAge:getAge
    }
}
var p1 = fn("張三");
p1.setAge(20);
console.log(p1.getAge());//20
console.log("姓名:"+p2.name+",年齡:"+p2.getAge()); //姓名:張三,年齡:20
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容