探索javascript中的this

若是你是个js的初学者,当决定使用js来开创一个新世界的时候,你会忽然遇到不少摸不到头脑的问题,好比继承,块做用域,或者如今的主题,this关键词。js中的this究竟是什么?咱们为何每次使用它的时候,都会忘记它的使用场景和环境。有时候当咱们尝试用以前的经验来处理的时候发现,what?为何跟个人设想不一致?那么好,如今你就能够花费你打一把游戏的时间,来跟随我看一下,this究竟是什么。
js的内存包括两个部分,执行栈和内存堆。js运行时会维护一系列的栈,当前的栈老是处在内存栈的栈顶,因此this变量就会随着栈的操做(pop/push)而改变指向的对象。es6

  1. 普通函数
    默认的执行栈是全局的,若是一段代码在普通函数中调用,this会指向默认的全局对象,window或者global,视运行环境而定。固然,若是咱们在代码中启用了严格模式use stirct;,那么在严格模式下,this指向的是undefined。能够参考如下的示例:数组

    function normalFunc() {
        console.log(this);
        console.log(this === window); // or global
    }
    function useStrictNormalFunc() {
        'use strict';
        console.log(this);
        console.log(this === window); // or global
    }
  2. 构造函数
    js中的构造函数,其实和普通函数没啥区别,除了它可使用new来实例化(可是普通函数也可使用new的啊)。哦还有一个区别,构造函数首字母是大写(固然没有任何规定,可是若是你小写,那确定会带来惊喜的)。app

    function Person(name) {
        this.name = name;
    }
    const person = new Person("fengxh");
    // person.name = "fengxh";

    当咱们使用new来实例化的时候,此时构造函数内的this指向的是实例对象,实例过程当中为实例创造了多个属性来达到咱们建立构造函数的目的,这样person其实就是被构建出来的实例。除非咱们手动为Person返回一个对象类型数据,不然Person默认返回的就是this(若是手动return基础数据,则也会被默认返回this)。函数

  3. 对象的方法调用学习

    function normalFunc() {
        console.log(this);
    }
    const person = {
        normalFunc
    };
    normalFunc(); // window or global or undefined
    person.normalFunc(); // yes, it's person. no!! why person

    对象的方法调用,this会指向对象自己,而不是全局变量。那么咱们接着再看。this

    const myFunc = person.normalFunc;
    myFunc(); // window or global

    哈哈,这里由于myFunc是普通的函数调用,因此this仍是指向到全局变量,而不是person了。那么,咱们再接着看。rest

    const person = {
        normalFunc: function() {
            console.log(this); // person
            function innerFunc() {
                console.log(this); // window or global
            }
            innerFunc();
        }
    };

    这里innerFunc仍是做为一个普通函数被调用,因此this指向为全局变量。固然这里的函数定义都是普通定义,若是遇到箭头函数,那么状况又会不同,这种状况咱们随后再说。code

  4. call,apply和bindorm

    const a = {
        name: "a"
    };
    const b = {
        name: "b"
    };
    function log() {
      console.log(this.name); 
    }
    log.call(a); // "a"
    log.call(b); // "b"
    log(); // undefined

    若是咱们在执行时改变this的绑定,那么会产生意外的惊喜,函数中的this会被绑定到咱们指向的那个对象,而不是全局变量window。Interesting。call和apply均可以动态改变函数中的this指向,他们的不一样点是call的参数第一个是改变this的绑定指向,第二个及之后都是做为普通函数的参数被调用,而apply的第一个参数和call同样,第二个函数则是参数数组,等同于arguments。而bind则是修改函数的this指向的对象,而后返回一个函数,不一样于前二者都是直接会调用对象

  5. 箭头函数
    详细定义的地方请看阮大师的介绍箭头函数定义
    箭头函数是不持有this的,因此它的this是属于外层的(此处不彻底精确,但愿读者能够自行阅读相关文献)。并且它不能做为构造函数使用,不能被call/apply/bind处理来达到改变函数里this指向的目的,它不持有this。

好了,看完这篇文章你们有没有学习到,有没有总结出下次遇到this再怎么处理它的问题。若是你们有什么疑问,或者对文章的理解有不一样之处,请指出互相学习。谢谢。

相关文章
相关标签/搜索