zoukankan      html  css  js  c++  java
  • 五分钟看懂js关键字this

    this是js里面很常用的关键字,而灵活的js也赋予了这个关键字无穷的生命力,相信你也有被它糊弄的时候,我总结了一个6字原则,大部分场合都能清醒分辨this到底指向who,跟大家分享一下,欢迎指正。

    谁调用指向谁!

    首先介绍一个大boss: window, 他是一个隐形大侠,没有确定的调用者的时候,肯定是它出手, 也就是说,如果一个对象没有显性的调用者时,this指向的就是window。

    先看下面的例子:

    var x = 10;
    function test(){
        console.log("--- test this.x---");
        console.log(this.x);
    }
    var fruit = {
        x: 20,
        apple: function(){
            console.log("--- apple this.x---");
            console.log(this.x);
        }    
    };
    
    fruit.banana = function(){
        var y = 20;
        this.z = 20;
        function pear(){    
            console.log("--- pear this.x---");    
            console.log(this.x);
        }
        console.log("--- banana y---");
        console.log(y);
        console.log("--- banana this.y---");
        console.log(this.y);
        console.log("--- banana this.z---");
        console.log(this.z);
        pear();
    }
    
    var myfruit = {
        x: 30
    }
    myfruit.mylove = fruit.apple;
    
    test();
    fruit.apple();
    fruit.banana();
    test.call(fruit)
    myfruit.mylove();
    example 1

     运行结果分析:

     1 --- test this.x---
     2 10  // this: window
     3 --- apple this.x---
     4 20 // this: fruit
     5 --- banana y---
     6 20
     7 --- banana this.y---
     8 undefined // this: fruit, we have not assign y to fruit.
     9 --- banana this.z---
    10 20 // this: fruit
    11 --- pear this.x---
    12 10 // this: window
    13 --- test this.x---
    14 20 // this: fruit, it is fruit to call test.
    15 --- apple this.x---
    16 30 // this: myfruit

     从上述结果可以看到:

    test();
    // test()的调用者为隐形boss, this指向window。
    fruit.apple();
    // apple()的调用者为fruit, this指向fruit。
    fruit.banana();
    // banana()的调用者为fruit, this 指向fruit。
    // 而banana()里面的pear(), 没有显性的调用者,尽管pear()在banana()定义,但是pear()为隐形boss调用,this指向的是window。
    test.call(fruit)
    // test()在window层面定义,然而实际调用者为fruit,所以this指向fruit。
    myfruit.mylove();
    // mylove()直接采用了apple()的定义,实际调用者为myfruit,并非fruit,所以this指向myfruit。

    综上所述,6字原则可以非常完美的指认this是谁。 这种简单粗暴的方法屡试不爽。谁调用指向谁!! 

    温馨提示

    在回调函数中使用this, 请谨慎谨慎谨慎。先上example: 

    var x = 10;
    var fruit = {
        x: 20
    };
    
    fruit.slice = function(callback){
        console.log("--- slice ---");
        console.log(this.x);
        console.log("--- callback begin---");
        callback();
    }
    
    fruit.slice(function(){
        console.log("--- callback output---");
        console.log(this.x);
        
    });
    example 2

     输出结果如下:

    1 --- slice ---
    2 20
    3 --- callback begin---
    4 --- callback output---
    5 10

    回调函数里边的this竟然指向window!!!

    我也被这个坑得不轻,回调函数里边的this并非指向宿主函数(调用回调函数的函数)的调用者,6字原则在这里还是非常灵光的,callback()调用时有显性调用者吗?没有!!!!因此,this指向是隐形boss window啦。

    当然,例子中希望回调函数指向fruit也不难,call可以帮你忙,请看例子。

    var x = 10;
    var fruit = {
        x: 20
    };
    fruit.slice = function(callback){
        console.log("--- slice ---");
        console.log(this.x);
        console.log("--- callback begin---");
        callback.call(this);
    }
    
    fruit.slice(function(){
        console.log("--- callback output---");
        console.log(this.x);
        
    });
    example 3

    妥妥输出:

    --- slice ---
    20
    --- callback begin---
    --- callback output---
    20

    再强调一遍,6字原则在确定js关键字this是谁的问题上屡试不爽, 谁调用指向谁!言下之意,没有调用者就是隐形boss window

    细心的看官也许会问, 第一个例子中的pear(), 既然里边的this指向window, 为什么不能在全局域中使用window.pear() or pear()呢?

    Good question!

    把这个问题用代码还原其实是这样:

    var fruit = {};
    fruit.banana = function(){
        function pear(){}
    }
    
    // 这样调用会出错咯
    pear();
    // 这样调用也不行
    window.pear();

     这两种方式调用都有exception,因为pear()只能在banana里面assign给banana的变量,或者在banana内部调用。

    这样调用是对的;

    var fruit = {};
    fruit.banana = function(){
        this.callPear = pear; // assign 给callPear
        function pear(){ console.log("I am pear!");}
       pear(); // 内部调用
    }
    
    var instant = new fruit.banana();
    instant.callPear();

     这涉及另外一个话题,作用域,scope!下次再跟大家详细分享scope。

  • 相关阅读:
    Network In Network
    UNIX环境高级编程之第4章:文件和文件夹-习题
    SqlServer 错误日志切换和查看
    hihoCoder
    Mono源码学习笔记:Console类(四)
    Java transientkeyword使用小记
    高速排序算法具体解释与实现
    The Triangle
    iOS开发实践之GET和POST请求
    C#重构经典全面汇总
  • 原文地址:https://www.cnblogs.com/haihai1203/p/5695920.html
Copyright © 2011-2022 走看看