zoukankan      html  css  js  c++  java
  • this指向

    1.全局上下文中 this

    /*
    1.全局上下文中的 this
    
    node环境下:
        
        严格模式下: {} {} 报错
    
        非严格模式下:{} {} {}
     */
    
    'use strict'; // 严格模式
    
    // demo 1:
    console.log(this);  // {}
    
    // demo 2:
    var a = this;
    console.log(a); // {}
    var b = 1;
    console.log(global.b); // undefined
    
    // demo 3:
    b = this; // 注意:严格模式下,变量必须得声明;非严格模式,可以省略声明符
    console.log(b); // {}
    c = 1;
    console.log(global.c); // 1
    
    /*
    分析:
    
        node环境下:
    
        node环境下 的上下文组成 与 浏览器环境下 有些不同;
    
        扩展了解一下,Node.js的全局对象 global:
    
        定义:Node.js中的全局对象是 global, 所有全局变量(除了 global 本身以外)都是global对象的属性;
    
        在 Node.js 中,我们可以直接访问到 global属性,而不需要在应用中包含它;
    
        也就是说,global 是全局对象,但是它还是 global.global的属性值,这是递归的过程;
    
        这跟浏览器下的 window对象 是一个逻辑,window对象还是 window.window 的属性值;
    
        全局对象 与 全局变量的关系:
    
        global的根本作用是作为全局变量的宿主,按照 ECMAScript的定义,满足以下条件的变量为全局变量:
    
            1.在最外层定义的变量
    
            2.全局对象的属性
    
            3.隐式定义的变量(未定义直接赋值的变量)
    
        当你定义一个全局变量时,这个变量同时也会成为全局对象的属性,反之亦然。需要注意的是,在 Node.js中你不可能在最外层定义变量,
    
        因为所有用户代码都是属于当前模块的,而模块本身不是最外层上下文。
    
        注意:永远使用 var 定义变量以避免引入全局变量,因为全局变量会污染命名空间,提高代码的耦合风险。
    
        所以,以上三个demo 获取 this 的方式:
    
        demo 1: 直接获取 this, 实际上 demo 1 创建执行上下文的过程是在 当前模块中进行的,所以说这个模块的上下文环境才是,demo 1 代码执行时的执行上下文,
    
            也就是说 环境对象是当前模块对象,而这个模块对象是个 新对象{},而结果输出 {}, 也就符合“this 指向其执行上下文的环境对象”这一结论了;
    
        demo 2: 根据定义,由于用var 声明的变量,实际上并不是在最外层上下文中声明的变量,是在当前模块声明的变量(global.b 值为 undefined,已经证明这点了),
    
            但是,整个代码的执行过程还是在 当前模块的上下文中进行的,同上 输出 {},也就符合“this 指向其执行上下文的环境对象”这一结论;
    
        demo 3: 可以看出 demo 3 在非严格模式下隐式定义了一个变量,并且给它赋了值,根据全局变量的定义,这样隐式定义变量的方式,
    
            实际上是在全局对象上定义一个属性,也称为全局变量,所以 通过 global对象可以获取到(global.c 的值为 1,已证明这点);
    
            但是要弄清楚,在这个全局变量的 定义过程,还是在 当前模块进行的,所以 此时 this指向依然是 当前模块的执行上下文对象 {};
    
            所以,“this 指向其执行上下文的环境对象” 这一结论依然成立;
    
    总结:
    
        Node环境下:
    
            全局的执行上下文 进行的过程是在 当前模块下进行的,所以全局执行上下文的环境对象是当前模块{},所以全局中 this 指向当前模块对象{};
     */

    2.函数上下文的 this

    /*
        2.函数上下文中的 this
    
        Node环境下:
    
            严格模式下: this 指向被指定的环境对象,即使指定的是 null 或者 undefined;
    
            非严格模式下:this 指向被指定的环境对象,如果指定的是 null 或者 undefined,会转为全局对象 global对象; 
         */
    
    "use strict"
    
    // demo 1:
    function aa(){
        console.log(this);
    }
    
    aa(); // 作为单独函数执行(没有指定 环境对象):strict-->"undefined"    nostrict-->"global"
    
    
    // demo 2:
    var obj = {
        a: 1,
        b: function(){
            console.log(this);
        }
    }
    
    obj.b(); // 作为对象方法执行: strict-->obj    nostrict-->obj
    
    // demo 3:
    aa.call(obj); // 作为单独函数执行(指定 环境对象为 obj): strict-->obj    nostrict-->obj
    
    // demo 4:
    aa.call(null); // 作为单独函数执行(指定 环境对象为 null):strict-->null    nostrict-->global
    
    // demo 5:
    aa.call(undefined); //作为单独函数执行(指定 环境对象为 undefined):strict-->undefined    nostrict-->global 
    
    /*
    总结:函数上下文中的 this
    
    Node环境 严格模式下:
    
        函数作为单独函数 执行:
    
            1.函数执行上下文的环境对象 是指定的,指定什么就是什么;this指向这个指定的环境对象;即使指定的是 null 或者 undefined;
    
        函数作为对象方法 执行:
    
            2.这个函数执行上下文的环境对象就是这个拥有它的对象;this指向这个拥有它的对象;
    
    
    Node环境 非严格模式下:
    
        函数作为单独函数 执行:
    
            1.函数执行上下文的环境对象 是指定的,指定什么就是什么;this指向这个指定的环境对象,如果指定的是 null 或者 undefined,会转为全局对象 global对象; 
    
        函数作为对象方法 执行:
    
            2.这个函数执行上下文的环境对象就是这个拥有它的对象;this指向这个拥有它的对象;
     */

    3.对象属性中的 this

    /*
        3.对象属性中的 this
    
        注意:这里指的是如下的形式,不要把它和 对象方法中的 this搞混;对象方法中的 this,要规划到 函数上下文的 this中; 
    
        Node环境下:
            
            严格模式下:{}
    
            非严格模式下: {}
     */
    'use strict'
    var obj = {
        a: 1,
        b: 2,
        c: this,
        sayHi: function(){
            console.log('Hi');
        }
    }
    
    console.log(obj.c);    // {}
    
    /*
        分析:
    
            其实,这样的对象字面量的形式,可能看起来会有些困惑,我们可以变形来分析;因为对象字面量的形式,实际上是由如下的形式简化而来的写法;
    
            var obj = new Object();
            obj.a =1;
            obj.b = 2;
            obj.c = this;
            obj.sayHi = function(){
                console.log('Hi');
            }
            
            这样看来就清晰很多了,上边这段代码执行的时候,不就是把全局执行上下文的环境对象赋给 obj.c 属性吗,关于 Node中全局上下文的环境对象 为 一个新对象{},我们已经介绍过了;
    
            而且结果,也正符合我们此时所得出的结果;
    
            所以,这样作为对象中的 this,可以规到全局执行上下文中的 this 一类中,this 指向 全局执行上下文的环境对象{};
    */
    /*
        一个例子,可能没有什么说服力,我们再来个嵌套形式的 来证实我们的结论, 如下:
     */
    var o1 = {
        a: 1,
        b: this,
        o2: {
            a: 1,
            b: this
        }
    }
    
    console.log(o1.o2.b); // {}
    /*
        结果依然是 {}, 其实 如上的形式,可以变形为:
    
        var o1 = new Object();
        o1.a = 1,
        o1.b = this;
        o1.o2 = new Object();
        o1.o2.a = 1;
        o1.o2.b = this;
        
        上面这段代码 在执行时,它的执行上下文的环境对象依然是 全局上下文的环境对象;所以说 this依然指向 {};
    
     */
    
    /*
        概括:对象属性中的 this指向为 全局执行上下文的环境对象{};
    */

    4.构造函数 和 原型方法中的 this

    /*
        4.构造函数 和 原型方法中的 this
    
        浏览器环境下:
            
            严格模式下:以构造函数名命名的新对象
    
            非严格模式下: 以构造函数名命名的新对象
     */
         "use strict"
         
         function Person(){
    
            console.log(this);    // Person {}
    
            this.name = 'jack';
    
            console.log(this);    // Person {name: "jack"}
        }
    
        Person.prototype.sayThis = function(){
            console.log(this);
        }
    
        Person.prototype.sayThis();    // {sayThis: ƒ}
    
        new Person();    // Person {} --> // Person {name: "jack"}
        
        /*
        分析 1:
         
            构造函数与普通函数的最重要的不同之处,就是构造函数可通过 new操作符,创造实例;
    
            那么在利用构造函数创造实例的过程到底发生了什么呢? 其实呢,是要经历以下几个过程的:
    
                1.创造一个 新对象,作为执行上下文的环境对象;(注意:这里为什么说成是新对象,而不说成是空对象呢,因为 function默认是有 prototype属性存在的,它指向原型对象)
    
                2.构造函数开始执行,它的执行上下文环境对象就为这个新对象,也就是说 this指向这个新对象;
    
                3.利用 this来给这个新对象赋值;
    
                4.返回这个被赋值之后的 新对象;
            
            通过上面 new Person() 执行后输出的结果来看,确实是这样的一个过程;没有没给 this赋值前输出的是 Person{}, 赋值后,输出的 Person{name:'jack'};
    
            所以 概括:
    
                构造函数中的执行上下文的环境对象为,以构造函数名命名的新对象;
    
        分析 2:
    
            至于原型方法中 this, 其实,在我们了解了 “函数上下文的 this” 之后,应该很清楚了,它指向给它指定的环境对象,也就是确定了的 构造函数的原型对象;
    
            所以,Person.prototype.sayThis() 执行后,输出的结果是 Person构造函数的原型对象 --> Person.prototype 对象;
         */

    5.应用 call、apply、bind 方法后的 this

        /*
        5.应用 call、apply、bind 方法后的 this
    
        了解:call、apply、bind 这三个方法是 Function对象才有的方法;它们的作用,主要是指定函数中 this中的指向,只是用法稍有不同;
        
        浏览器环境下:
            
            严格模式下:this指向 这三个方法所指定的这个值,无论是什么,即使是 null、undefined, this 也指向它们;
    
            非严格模式下:this指向 这三个方法所指定的这个值,null 和 undefined 值会被转换为全局对象 window;
    
         */
        
        "use strict"
        
        // demo 1:
        var o1 = {
            a: 11,
            b: 12,
            sayA: function(){
                console.log(this.a);
            }
        }
    
        var o2 = {
            a: 21,
            b: 22
        }
    
        o1.sayA.call(o2);    // 21
    
        // demo 2:
        function sayB(){
            console.log(this.b);
        }
    
        sayB.call(o2);    // 22
        sayB.apply(o2);    // 22
    
        var bSayB = sayB.bind(o2);
        bSayB();        // 22
        
        /*
        其实这块不应该单提出来一个作总结分析的,完全可以规划到“函数上下文的 this”中去,只是在我们平时 coding的时候, 
    
        这三个方法是经常要用到的 所以单拿出来,以作记忆吧;
    
         */    

     原创:转载注明出处,谢谢 :)

  • 相关阅读:
    集合框架之——迭代器并发修改异常ConcurrentModificationException
    Python day 3 (3) 判断与循环
    hdu 5335 Walk Out(bfs+斜行递推) 2015 Multi-University Training Contest 4
    hdu 2473 Junk-Mail Filter(并查集_虚节点)2008 Asia Regional Hangzhou
    hdu 1573 x问题(中国剩余定理)HDU 2007-1 Programming Contest
    hdu 3461 Code Lock(并查集)2010 ACM-ICPC Multi-University Training Contest(3)
    hdu 2155 小黑的镇魂曲(dp) 2008信息工程学院集训队——选拔赛
    hdu 4081 Qin Shi Huang's National Road System(最小生成树+dp)2011 Asia Beijing Regional Contest
    hdu 3938 Portal(并查集+离线+kruskal)2011 Multi-University Training Contest 10
    hdu 3172 Virtual Friends(并查集)University of Waterloo Local Contest 2008.09
  • 原文地址:https://www.cnblogs.com/cnblogs-jcy/p/8909929.html
Copyright © 2011-2022 走看看