重学前端之 让人心态爆炸的this究竟是个什么玩意

一.前言

两年前,曾经的组长对我说过,一个前端连闭包原型this都搞不明白,还好意思说本身是前端。以后我一直去试着理解this,看了好多博客和视频教学,发现好像并非特别好理解。可是在以后的项目中,我都使用了this。在接触和使用事后,好像对this有点了解,特别写一篇博客记录一下关于this的二三事,方便之后查询,也给刚刚接触前端的小伙伴一点点帮助前端

二.this是什么?

首先this在js中理解起来很简单,他就是当前对象,也能够理解成指向的对象,那么问题来了,那么我怎么知道当前指的是那个对象?bash

三.this的到底指向的是谁?

首先咱们想理解this的话,咱们必需要理解两句话
全局变量是window的属性,函数是window的方法
this谁最后调用,他就是谁闭包

首先咱们理解一下使用代码理解一下app

let a = '5'
console.log(window.a)  //5
function foo(){
    reutrn 'foo'
}
console.log(window.foo())   //foo
复制代码

咱们申明了一个全局变量a和一个函数foo,可是咱们调用他们的时候并无直接调用,而是使用window这个全局对象调用来调用属性和方法的方式调用,因此能够看到打印出他们的值,能够得出全局变量是window的属性,函数是window的方法这一结论 而后咱们运行代码函数

var name = 'Tom'
function name(){
    var name = 'Jerry'
    console.log(this.a)
}
name()  // 'Tom'
console.log(this)   //window
复制代码

在全局做用域中,函数是window的方法,name函数由window调用,那么函数内部的this指向的就是window,固然打印出出的this.name固然就是全局做用域下的name值了 简单了解了this的指向,咱们细分一下几个复杂场景下面的this指向(this究竟是谁)学习

在函数内部嵌套的内部函数

var name = 'apple'
    function fn0(){
        var name = 'Tom'
        function fn1(){
            console.log(this.name);
        }
        fn1();
    }

    fn0();
复制代码

函数内部嵌套的内部函数,依然指向全局对象(window)ui

在构造函数中和对象中

function Person(name){
        this.name = name;
        this.say = function(){
          console.log('Hello'+this.name)
        }
    }
    Person.prototype.printName = function(){
        console.log(this.name);
    };
    
    var a = new Person('Byron');
    a.say()     //"HelloByron"
    a.printName()   //"Byron"
复制代码

在构造函数中,this的指向就调用他这个对象的方法,不管是否在原型上this

var name = 'apple'
var obj1 = {
    name: 'Byron',
    fn : function(){
        console.log(this.name);
    }
};
obj1.fn()   //  Byron
复制代码

在对象中使用也是同样,this的指向在就是他调用他这个对象上 这里有个小陷阱,加上代码看一下spa

var fn2 = obj1.fn;
fn2();  //'apple'
复制代码

咱们把方法赋值给一个变量,直接用变量调用看看,这个时候咱们就能够看出来,this的指向改变了,变成全局的了,符合咱们上面的第二句话,this谁最后调用,他就是谁prototype

setTimeout、setInterval

在setTimeout、setInterval的内部函数中,不管是谁调用,他指向的都是全局变量

var name = 'apple'
var obj1 = {
    name: 'Byron',
    fn : function(){
       setTimeout(function(){
           console.log(this.name)
       },300)
       setInterval(function(){
           console.log(this.name+'666')
       },300)
    }
};
ob1.fn()    //apple
            //apple+666
fn1 = obj1.fn
fn1()       //apple
            //apple+666
复制代码

能够看得出来,打印的结果能够得出this指向的都是全局对象window

DOM对象绑定事件

document.querySelector('input') = function(){
    console.log(this.value)
}
复制代码

DOM对象绑定事件中的函数中的this指向的是当前这个DOM节点

箭头函数

箭头函数中,this的指向有点特别:建立时的封闭词法上下文的this保持一致

var name = 'tom'
var obj1 = {
    name :  'Byron',
    fn :function(){
        setTimeout(()=>{
        console.log(this.name)
      },0)
    }
};
obj1.fn() //'Byron'
复制代码

因为箭头函数特殊的缘由,箭头函数没有原型,因此箭头函数自己没有this,他只能指向定义外层第一个普通的this,那若是那个普通的this变化了,箭头函数中的this会指向哪呢?

var name = 'tom'
var obj1 = {
    name :  'Byron',
    fn :function(){
        setTimeout(()=>{
        console.log(this.name)
      },0)
    }
};
var obj2 = {
    name : 'hello world'
}
obj1.fn.call(obj2) //'hello world'
复制代码

能够看出若是外层的this变化了,箭头函数内的this会随着外层的变化而变化

四.总结

1.this的指向不是固定的,是会变化的(这篇博客尚未讲call,apply,bind等函数的用法)
    2.this谁调用他,他就指向谁
    3.在setTimeout、setInterval中,不使用箭头函数的状况下this指向全局对象window
    4.箭头函数没有原型,this指向外层做用域
复制代码

五.结语

想要完全了解this,必须在项目中多多使用this,遇到问题打印一下,结合网上的博客分析为何会这样,这样学习起来也比较快,理解也能加深,毕竟学习一个东西的最好的方法就是去使用他。若是文中有错误,但愿你们在评论里面提出指正,本人加以改正

相关文章
相关标签/搜索