• javascript执行原理


    执行环境

    当执行流执行到函数时会创建一个执行环境,这个执行环境包含了函数内部 语句可以访问的所有变量和函数,当代码执行完时,销毁执行环境。所以一般情 况下,局部变量在函数执行完时会被销毁。

    作用域、调用对象

    很多人认为作用域是在函数执行时创建的,这是有偏差的理解!

    作用域分词法作用域和动态作用域:

    •  词法作用域是在函数定义的时候创建的,作用域的本质是创建它的外层函数的调用对象组成的对象链,函数内部属性[[scope]]指向此作用域。
    •  当调用函数时,会创建一个调用对象(有些地方称活动对象),这个调用对象保存了函数参数和局部变量。将此调用对象推入词法作用域的前端,因此执行时作用域发生了变化,称为动态作用域。

    实质上作用域只有一个,都是内部属性[[scope]],词法作用域和动态作用域是时间上的不同造成的划分。作用域链是一条对象链,函数自己的活动对象,接着是父函数的活动对象,接着是祖父函数的活动对象。。。。 函数执行时,是沿着作用域链去寻找标识符的值的,先从自己的活动对象开始。 with、catch 会改变动态作用域,将with的对象和catch的对象压入作用域链前端。

    下面出个例子看你是否对作用域链理解到位了:

    var obj = {a:1,b:2};
    var fn = function(){
         var c=3;
         var a = 5;
         console.log(a);   //a等于多少?
         with(obj){
             a=6;                        
             return function(){return a+c;};
         }
    }(); 
    fn();     //结果是多少?

    闭包  

    啥是闭包?

    官方:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。

    民间:内部函数拥有外部函数的环境。

    通俗的就是内部函数可以访问外部函数的变量。

    形成机理:作用域链。

    内存及变量查找效率

    当有闭包,且内部函数赋给了外部变量引用时,要特别注意内存 。没有赋给外部变量时,代码执行完后执行环境销毁,不会有变量贮存内存。但赋给了外部变量时,闭包的词法作用域链会持有外层函数的活动对象,使得外部的变量不会回收。为了有效回收应该将变量设为null,断开引用。

    var fn = function(){
        var div = document.getElementById("div");
        return function(){};    
    };  //div不会销毁

    根据作用域链的原理,处于作用链前端的变量会更快找到,所以尽量用局部变量。

    1 var a,b,c;
    2 var fn = function(){
    3     var d,e,f;
    4     return function(){ 
    5         var h,j,k; 
    6          return typeof nothing; //nothing这个变量查找了整条作用域链,直到查询到window中这个变量,才返回"undefined".
    7     };    
    8 };

    this

    this跟arguments一样是函数执行时,活动对象的一部分。this是动态的,函数执行时候绑定。

    大概有这几种情况:

    (1) 函数,this==window

    var fn = function(){console.log(this==window);}; //true
    
    fn(); //不管函数fn在任何地方定义,是顶层函数,还是嵌套 ,this都等于window

    (2) 方法,this==obj

    var obj = {};
    
    obj.fn = function(){console.log(this==obj);}; //true
    
    obj.fn();

    (3)setTimeout setInterval,this==window

    var obj = {};
    
    var fn = function(){console.log(this==obj);};
    
    setTimeout(fn,1000); //?
    
    obj.fn = fn;
    
    setTimeout(obj.fn,1000); //?

    (4)call,apply将函数or方法绑定给了对象,this==obj

    var obj = {};
    
    var fn = function(){console.log(this==obj);}; //true
    
    fn();
    
    fn.call(obj);

    (5)事件处理程序

    DOM0

    btn.onclick = function(){console.log(this==btn);}; //true

    DOM2

    btn.addEventListener("click",function(){
         console.log(this==btn);        //true
    },false);

    IE

    btn.attachEvent("onclick",function(){
          console.log(window==btn);   //true
    });
  • 相关阅读:
    string转double后,因为精度问题的解决方法
    markdownpad 2 pro
    JDK的最详细的安装教程 环境变量详解
    办公实用工具分享
    前端页面展示时分秒倒计时
    M1芯片搭建IOS开发环境全记录
    前端报404时,你不知道的出错原因
    生成新的DICOM图像示例
    Python私有属性和私有方法面试题
    Python property属性练习
  • 原文地址:https://www.cnblogs.com/xuntu/p/3618896.html
Copyright © 2020-2023  润新知