美文网首页JS闯关之路让前端飞
Javascript基础进阶(一)

Javascript基础进阶(一)

作者: icessun | 来源:发表于2018-03-07 22:55 被阅读8次

    变量提升

    javaScript程序并不全是从上往下一行一行执行的,在执行的过程中有两个阶段:

    • 词法解释(编译阶段)
      在程序执行过程的时候,先在整个文件中,查找带var 声明的变量,不带var 的变量是全局变量,全局变量是不会提升的,若有带var 声明的变量或者function声明的函数就提到该语句的当前作用域的最前面
    • 运行阶段(代码从上往下按顺序执行)
    a = 'icessun';
    var a;
    console.log(a);      // icessun
    ------------------------------------------
    console.log(a);
    var a= 'icessun';   // undefined
    

    对于语句:var a='icessun',这执行的时候分两步:

    1. 声明变量 var a -----编译阶段(词法解释)
    2. 赋值 a='icessun' ------运行阶段,赋值是在变量当前位置进行赋值
    // 函数声明方式
    function show(){
       console.log('icessun');
    }
    
    // 函数表达式
    var show =function(){
         console.log('icessun');
    }
    

    函数声明的时候,在其前面调用和后面调用都可以;函数表达式,在其前面调用是不行的。

    因为函数声明会提升到当前作用域的最前面。函数表达式不会这样提升,按照前面的理解:当在函数表达式前面调用show(),就相当于

    var show;
    show();  // 相当于是===> undefined ()  报错
    show = function(){  
        console.log('icessun');
    }
    

    当出现函数声明与变量声明同名的情况,函数声明会被优先提升,变量声明被忽略,函数表达式不会被提升。下面程序的执行结果是icessun

    show();
    var show;
    function show(){   // 函数声明
        console.log('icessun');
    }
    show = function(){  // 函数表达式
        console.log('hi');
    }
    ---------------------------------------
    解释后,相当于:
    function show(){   // 函数声明 提升到当前作用域的最前面  var show;被忽略
        console.log('icessun');
    }
    show();   // 输出  icessun
    show = function(){  // 函数表达式
        console.log('hi');
    }
    ----------------------------------------
    show();  // icessun
    var show;
    function show(){   // 函数声明
        console.log('icessun');
    }
    show()  // icessun
    show = function(){  // 函数表达式
        console.log('hi');
    }
    show()  // hi
    

    如果出现多个同名函数声明,后面的就会把前面的覆盖:

    show();  // icessun1
    var show;
    function show(){   // 函数声明
        console.log('icessun');
    }
    show = function(){  // 函数表达式
        console.log('hi');
    }
    function show(){   // 函数声明
        console.log('icessun1');
    }
    -----------------------------------
    解释后,相当于:
    function show(){
       console.log('icessun1');    // 后面的把前面的覆盖
    }
    show();
    show = function(){  // 函数表达式
        console.log('hi');
    }
    -----------------------------------
    show();  // icessun1
    var show;
    function show(){   // 函数声明
        console.log('icessun');
    }
    show = function(){  // 函数表达式
        console.log('hi');
    }
    function show(){   // 函数声明
        console.log('icessun1');
    }
    show();  // hi
    

    下面的程序执行报错,提示说show不是一个函数;这是因为,在预解释的时候,IF里面的函数会进行提升,但是不会提升到IF外面去,而是在IF内部的最前面(当前作用域最前面)。

    var a=true;
    show();
    if(a){
        function show(){
           console.log(1);
        } else{
            function show(){
                console.log(2);   
             } 
        }
    }
    

    this关键字指向

    this:上下文,会根据当前执行环境变化而变化

    • 单独的this,指向的是window这个全局对象
    alert(this);  // this----->window
    
    • 全局函数中的this,指向的是window这个全局对象
    function show(){
        alert(this);  //  this----->window 调用全局函数,是在全局作用域里面执行,所以执行window
    }
    show();
    
    • 使用call / apply的方式调用函数(程序运行的时候才改变this指向)
    function show(){
        alert(this);  //  this----->abc,指向call里面传入的对象
    }
    show.call('cab');
    ----------------------------------
    特殊情况:
    function show(){
        alert(this);  //  this----->window 
    }
    show.call(null);   //  this----->window 
    show.call(undefined);   //  this----->window 
    ---------------------------------
    给函数传参数:
    function show(a,b){
         alert(this+'\n' +'a:' +a+'b:'+b);
    }
    show.call('icessun',10,20);  // 第一个参数传给this,后面是a,在后面是b,如果不对形式参数传递参数,默认是undefined
    -----------------------------
    apply情况:传递参数的时候,后面的参数使用数组包裹起来
    ---------------------------------
    function show(a,b){
         alert(this+'\n' +'a:' +a+'b:'+b);
    }
    show.apply('icessun',[10,20]);  // 第一个参数还是this值,后面数组的值是形式参数值a:10;b:20
    
    
    • 定时器中的this,指向的是 window
    setTimeout(function(){
         alert(this) ;//  this----->window
    },500)
    
    • 元素绑定事件,事件触发后,执行的函数中的this指向的是当前的元素(触发事件的元素)
    <input>点我</input>
    window.onload=function(){
        var oBtn=document.querySelector('input');
         oBtn.click=function(){
             alert(this);// this指向当前触发事件的元素对象(按钮)
             alert(this.value);  // 点我
        }
    }
    
    • 函数调用时,如果绑定了bind,那么函数中的this就指向bind中绑定的东西(程序未运行的时候,预解释的时候就改变了this指向,就已经确定了this的指向)
    var a=10
    window.onload = function(){
         var  oBtn = document.querySelector('input');
         oBtn.addEventListener('click',function(){
              alert(this);  //  this------->window  
              alert(this.a);  //  10
         }.bind(window));   //  用window替换了事件对象作为里面的this值
    }
    

    -对象中的方法:如果该方法被哪个对象调用,那么方法中的this就指向该对象

    var obj={
      userName:'icessun',
        show:function(){
             alert(this.userName); // this----->obj
       }
    };
    obj.show();
    -------------------------------
    var obj={
      userName:'icessun',
        show:function(){
             alert(this.userName); 
       }
    };
    var fn=obj.show;  // this------>obj
    fn();  // this------>window
    
    • 函数调用的时候,前面加上new关键字
    function show(){
        alert(this);  //  this----->object  对象   输出undefined
    }
    new  show();
    ----------------------------------
    这个对象是什么?
    function show(){
    //    alert(this);  //  this----->object  对象  
      this.userName = 'icessun'  // this就是指向的a对象
    }
    var a=new  show();
    alert(a.userName);
    
    // 面试题
    var x=20;
    var a={
      x:15,
      fn:function(){
          var x=30;
           return function(){
               return this.x;
           };
       }
    };
    console.log(a.fn());   // function(){return this.x}
    console.log((a.fn())()); // 相当于把返回的函数当作一个表达式,然后执行;也就是说把返回的函数作为一个自执行函数表达式。那么this指向window  返回20
    console.log(a.fn()()); // 把返回的函数执行,当作一个闭包,闭包里面的this指向window,返回20
    console.log(a.fn()()==(a.fn())()); // true
    console.log(a.fn().call(this)); // call里面的this是指向的window,因为这段代码是在全局作用域里面执行;this.x ====>window.x  ----> 20
    console.log(a.fn().call(a)); // call函数里面把a对象传入,this.x ======>a.x ------>15
    

    相关文章

      网友评论

        本文标题:Javascript基础进阶(一)

        本文链接:https://www.haomeiwen.com/subject/hxqvxftx.html