zoukankan      html  css  js  c++  java
  • js中this详解

    this对象是在闭包一节中提到的,书上的原话是:“this对象是在运行时基于函数的执行环境绑定的,在全局函数中,this等于window,而当函数作为某个对象的方法调用时,this等于那个对象,匿名函数的执行环境具有全局性,因此其this对象通常指向window。”也可以理解为this是指向函数所处作用域中的对象,决定this的就是当前的执行环境所在的作用域。

    下面是this的四种常见情况下的用法:

    1,纯函数调用,此时的this就是全局环境下的window,访问到的this对象的属性就是全局环境下定义的,而不是函数内部定义的。

    var a = 1;
    function fn(){
       var a = 0;
       console.log(this.a)
    };
    fn();    // 1

    同样的,如果直接在函数里面定义this的属性,那么也就相当于在全局下定义了window的属性。

    var a = 1;
    function fn(){
        this.a = 0;
    };
    
    console.log(a);    // 1;
    
    fn();
    
    console.log(a);    // 0;

    这里就直接覆盖掉了原先定义的a

    2,作为对象的方法来调用,此时的this对象就是指向调用它的那个对象(上级对象,离他最近的那个)

    var a = 0
    function fn(){
        console.log(this.a)  
    };
    var obj = {
        a: 1
    };
    obj.test = fn;
    obj.test();    // 1

    3,作为构造函数调用,this就是指向生成的新对象

    function fn(){
       this.a = 1
    };
    var o = new fn();
    o.a;    // 1

    此时的this不指向window

    var a = 0;
    function fn(){
       this.a = 1
    };
    var o = new fn();
    o.a;    // 1
    a;    // 0

    此时并没有执行fn(),所以全局环境下的a没有改变

    4,配合apply使用,此时的this就指向第一个参数,如果不传,就表示默认为全局环境

    var x = 0; 
    
    function test(){ 
    
      alert(this.x); 
    
    } 
    
    var o={}; 
    
    o.x = 1; 
    
    o.m = test; 
    
    o.m.apply(); //0 

    o.m.apply(o);    // 1

    当this所在的函数还没被调用的时候,this的指向是不明确的,只有被调用的时候,this才会明确所指对象,指向的是调用这个函数的对象

    一,下面来看几个例子

    function fn(){
        user: "Yan",
        console.log(this.user)
        console.log(this);
    }
    
    fn();   
    // undefined
    // window

    其实上面等同于下面这个:

    window.fn();

    这里fn()是被window对象调用的,作用域是全局环境下,所以这里的this指向window,而user在全局下未被定义;

    再看一个更清楚的

    var o = {
        user: 'Yan',
        fn: function(){
            console.log(this.user);
            console.log(this);
        }
    };
    o.fn();
    // Yan
    // {user: 'Yan', fn: f}

    这里调用fn()的是o这个对象,所以此时的this指向o。

    那如果是下面这种情况呢:

    window.o.fn();

    结果是跟上面那个一样,为什么呢?这里我们把最初的定义再说具体一点,

    this对象始终指向的是直接调用它的对象,这个对象就是它的上一级,就是最终输出的时候,a.fn()就是a,b.fn()就是b。。。

    下面这个例子也能很好的说明上面这段话:

    var o = {
        user: 'Yan',
        a: {
            user: 'Chen',
            fn: function(){
                console.log(this.user);
                console.log(this);
            }
        }
    };
    o.a.fn();
    // Chen
    // {user: 'Chen', fn: f}

    如果上面这个稍作改动,结果如何呢,来看:

    var j = o.a;
    j.fn();

    答案是还是一样的,因为这里的fn()是被对象j调用的,而对象j是o.a的复制,引用类型的复制,所以fn()被调用的还是a,所以this依然指向a

    但是下面这种情况就比较特殊了,来看:

    var h = o.a.fn;
    h();
    // undefined
    // window

    为什么这里的指向不是a了,因为h相当于复制了fn这个方法,而此时h()就等同于window.h(),那么此时的this指向的就是它的调用对象window。

    二,当this遇到构造函数的时候

    这个又要另当别论了,直接先看代码:

    function fn(){
        this.user = 'Yan'
    }
    var a = new fn();
    console.log(a.user);
    // Yan

    new关键字可以改变this的指向对象,这里的new创建了一个fn的实例a,相当于在a里面复制了一个fn,当执行a.user的时候,实际上就是指向的a,因为fn是a调用的。

    三,当this遇到return的时候

    先把结论说了,当return一个对象的时候(null除外),this指向的就是那个返回的对象,如果不是对象,指向的就还是原函数的实例。

    function fn()  
    {  
        this.user = 'Yan';  
        return {
        user: 'Chen'
      } }
    var a = new fn; console.log(a.user); // Chen
    function fn()  
    {  
        this.user = 'Yan';  
        return function(){};
    }
    var a = new fn;  
    console.log(a.user); // undefined

    null除外:

    function fn()  
    {  
        this.user = 'Yan';  
        return null;
    }
    var a = new fn;  
    console.log(a.user); // Yan

    不是对象的时候:

    function fn()  
    {  
        this.user = 'Yan';  
        return 1;
    }
    var a = new fn;  
    console.log(a.user); // Yan
    function fn()  
    {  
        this.user = 'Yan';  
        return undefined;
    }
    var a = new fn;  
    console.log(a.user); // Yan

    ==========================

    2018年7月3日补充

    当一个函数被调用时,会创建一个活动记录(有时候称为执行上下文),这个记录包含函数在哪里被调用(调用栈)、函数的调用方式以及传入的参数等信息,this就是这个记录的一个属性,会在函数执行的过程中用到。

    this既不指向函数自身也不指向函数作用域,它是在函数被调用时绑定的,指向什么完全取决于函数在哪里被调用。

    箭头函数本身没有this,取而代之的是当前的词法作用域覆盖了this本来的值。

  • 相关阅读:
    03_02_leetcode_11_盛最多的水
    03_01_跳跃表
    初学Java算法编程_Array List自己和官方文档的区别
    编译原理习题解析-第1章
    VS2019配置C+++mingW32配置
    自创理解绝对定位和相对定位的方法
    Solution -「洛谷 P7395」「CoE-I 2021C」弹珠游戏
    Solution Set -「ARC 113」
    Solution Set -「ABC 192」
    Solution Set -「CF 1486」
  • 原文地址:https://www.cnblogs.com/yanchenyu/p/7581668.html
Copyright © 2011-2022 走看看