js预编译和作用域链以及闭包

js中有暗示全局变量:任何变量如果未经声明就赋值,此变量就为全局对象所有(不管在哪里)。

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

window就是全局的域。一切声明的全局变量,全是window的属性。

var a = 123;
console.log(window.a) //123
  • js函数预编译四部曲

预编译结束后执行函数:

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(){}
}
  • 全局预编译三部曲:

    1、生成一个GO对象(Global Object)就是window
    2、找变量声明,将变量名作为GO属性名,值为undefined
    3、找函数声明(注意不是函数表达式),值赋予函数体。

知识点: 1、GO发生在AO前。 2、形参和实参有映射规定:形参变,实参也变。实参出生有几个就几个,不对应形参个数就不映射。3、typeof(NaN) // "Object"

作用域

运行期上下文:当函数执行前一刻,会创建一个称为执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被销毁。
[[scope]]:每个javascript函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供javascript引擎存取,[[scope]]就是其中一个。
[[scope]]指的就是我们所说的作用域,其中存储了运行期上下文的集合。
作用域链:[[scope]]中存储着执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。(每个函数都有自己的作用域链)
查找变量:在哪个函数中查找就从这个函数作用域链的顶端依次向下查找。(在全局定义的函数,它的运行期上下文就是全局域)。

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

//a函数被定义时产生 a.[[scope]] -->  0:GO{}
//a函数被执行时 a.[[scope]] --> 0:AO{}
//                             1:GO{}
//b函数被定义时 b.[[scope]] --> 0:AO{} a的AO
//                             1:GO{}
//b函数被执行时 b.[[scope]] --> 0:AO{} b的AO
//                             1:AO{} a的AO引用
//                             1:GO{}
a函数被定义时.png

a函数执行.png

b函数被定义时.png

b函数被执行时.png

闭包

当内部的函数被保存到外部时,将会生成闭包。闭包会导致原有作用域链不释放,造成内存泄漏。

function a(){
  function b(){
      var bbb = 234;
      consoloe.log(aaa);
  }
var  aaa = 123;
return b;
}
var glob = 100;
var demo = a();
demo();
闭包作用域链.png
  • 闭包的作用:
    • 1.实现公有变量
      • eg:函数累加器
    • 2.可以做缓存(存储结构)
      • eg:eater
    • 3.可实现封装,属性私有化。
      • eg:Person();
    • 4.模块化开发,防止污染全局变量
1.就是闭包实现累加
function add(){
  var count = 0;
  function demo(){
    count ++;
    console.log(count);
  }
return demo;
}
var counter = add();
counter(); //1
counter(); //2

2.可以做缓存(存储结构)
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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容