this

this

在工作和学习的过程中,我们会一不小心的掉进this的坑中,今天我们就来把这些坑给他填满,防止以后再入坑。

我们要填this的坑,那么就要先来了解一下什么是this

this是什么呢?

this是一个关键字,被自动的定义在所有函数的作用域中。而且this的指向非常的多变,它会根据调用者的不同而不同。

this在不同环境下的指向

  • 在全局的环境中
    废话不多说,直接上代码
    console.log(this); // window
    
    所以在全局的环境下,this的指向是window。这句话看似没有问题,但是却一点不严谨,因为大家都知道,js是分为两种模式的,一种是严格模式,一种是非严格模式。非严格模式我们已经试过了,那么接下来我们在看看在严格模式下的this是什么吧。
    'use strict'
    console.log(this); // window
    
    在严格模式的全局环境下,this的指向也是window。
    但是,这只是在浏览器的环境下,要是在node的环境下呢?我们一起来看看
    console.log(this);
    
    //接下来的代码是模拟在控制台中输入(假设这段代码是写在understandThis.js文件中)
    node understandThis.js
    {}   //返回了一个空对象
    
    在node的环境下,运行一个js文件,里面的一切都是属于这个js文件的,所以this指向的是module.exports。
  • 函数内部环境
    全局环境下,我们知道了,现在就来看看在函数内,this的指向是什么吧。

    function understandThis() {
            console.log(this)
        }
    understandThis(); // window
    

    在非严格模式的函数内,this的指向是window。我们在来看看在严格模式下的是什么情况。

    'use strict'
    function understandThis() {
        console.log(this)
    }
    understandThis(); // undefined
    window.understandThis(); // window
    

    在严格模式下,返回的是undefined,为什么会这样呢?
    因为在严格模式下,你需要严格的写出调用函数的对象,不可以有任何的省略。

  • 事件调用
    接下来我们就看看,在事件调用下,this的指向吧。

    //html代码
    <div class="one">1</div>
    <div class="two">2</div>
    
    //js代码
    var one = document.getElementsByClassName('one')[0];
    var two = document.getElementsByClassName('two')[0];
    function This() {
        console.log(this);
    }
    
    one.onclick = This; //<div class="one">1</div>
    two.onclick = This; //<div class="two">2</div>
    

    谁调用了This这个函数,那么this就指向谁。在严格模式中也是一样噢~

    //html代码
    <div class="one">1</div>
    <div class="two">2</div>
    
    //js代码
    'use strict'
    var one = document.getElementsByClassName('one')[0];
    var two = document.getElementsByClassName('two')[0];
    function This() {
        console.log(this);
    }
    
    one.onclick = This; //<div class="one">1</div>
    two.onclick = This; //<div class="two">2</div>
    
  • 构造函数中

    function understandThis() {
        this.name = 'xiaoqi';
        console.log(this); // {name: "xiaoqi"}
    }
    var a = new understandThis();
    console.log(a); // {name: "xiaoqi"}
    

    构造函数的调用方式和普通函数的调用方式不同,构造函数需要用new关键字来调用。当用new来调用这个函数的时候,会发生几件事件(隐式的):

    • 在构造函数的内部创建一个名为this的空对象
    • 然后在执行this.xxx = xxx;
    • 最后,要是构造函数没有返回值的话,会默认的返回this对象;如果设置的返回值是值类型,那么还是会返回this对象,如果设置的是引用值(函数、对象、数组),那么就会返回该引用类型。null是一个例外,如果是null的话,还是返回this对象。

    不管是在非严格模式下还是严格模式下,构造函数中的this指向都是使用该构造函数创建的实例对象。

  • 对象

    var obj = {
        fn: function() {
            console.log(this);
        }
    }
    obj.fn(); // obj
    var a = obj.fn;
    a(); // window
    var b = obj.fn(); // obj
    

    this有一个特点,那就是谁调用它,那么它就指向谁。
    明白这个道理之后,我们一个个来解答

    obj.fn(); // 因为这里是obj来调用它的,所以它当然指向obj啦
    
    var a = obj.fn;
    a(); //这边在全局环境下(window)创建了一个变量a,然后把obj.fn存储到变量a里面去,但是没有执行。因为变量a是储存在window对象中的,所有a()相当于window.a(),所以最后输出的是window
    
    var b = obj.fn(); // 这边虽然也是在全局下创建了变量b,但是它存储的是obj.fn()执行之后的结果,还是obj调用了fn函数。
    
  • 箭头函数

    var obj = {
        a: 10,
        fn: function(){
            console.log(this)
            console.log(this.a);
        },
        fn1: () => {
            console.log(this)
            console.log(this.a)
        }
    }
    obj.fn(); // obj 10
    obj.fn1(); // window undefined
    

    从上面的代码可以看出来,普通函数的this还是谁调用它,那么就指向谁;而箭头函数的this却不一样,虽然是obj调用它,但是它还是指向的window。难道在箭头函数内,this是指向window的吗?我们在来看看下面的代码

    var obj = {
        b : function () {
            (() => {
                console.log(this);
            })()
        }
    }
    obj.b(); // obj
    

    这段代码中的this指向了obj,为什么会这样呢?

    因为箭头函数它本身是没有this的,它会捕获自己位置上下文的this值来作为自己的一个this值。因为这段代码中,是obj调用了b函数,让b函数里面的this指向了obj,然后被箭头函数所捕获,所以此刻箭头函数内的this也变成了obj。

  • call() 、apply() 、 bind()
    有没有什么方法,可以改变this的指向呢?当然有啦,今天他们来了!

    首先出场的是call()

    var obj = {
        b : function (a, b, c) {
            (() => {
                console.log(this, a, b, c);
            })()
        }
    }
    var box = {};
    obj.b.call(box,1 ,2 ,3); // {} 1 2 3
    

    原本this应该是obj的,但是用call改变了this的指向,现在this指向了box。我们再来看看它的兄弟appy()

    var obj = {
        b : function (a, b, c) {
            (() => {
                console.log(this, a, b, c);
            })()
        }
    }
    var box = {};
    obj.b.apply(box,[1 ,2 ,3]);  //// {} 1 2 3
    

    他们两个除了传参列表的不一样,其他都差不多。

    方法 第一位参数 剩余参数
    call() 改变this指向的参数 把实参按照形参的个数传进去
    apply() 改变this指向的参数 传入一个数组(arguments)

    现在我们再来看看bind(),它和其它两个都不一样,具体哪里不一样呢?看下面的代码

    var obj = {
        a: 1
    }
    
    var obj1 = {
        b: function() {
            console.log(this.a)
        }
    }
    obj1.b.bind(obj)(); // 1
    

    原本在obj1的作用域中是没有a这个属性的,直接执行obj1.b()会返回undefind,现在通过bind方法改变this的指向,让this指向为obj,这样输出的就是obj里面a的属性值了。而且bind返回的结果是一个函数,你需要再去执行它。

    后续我会再写一篇关于 call() 、apply() 、 bind() 的笔记,记得关注哟~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355