• this指向


    1.全局上下文中的 this
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>this 指向</title>
    </head>
    <body>
    <script type="text/javascript">
        /*
        1.全局上下文中的 this
    
        浏览器环境下:
    
            严格模式下: Window
    
            非严格模式下: Window
         */
        
        'use strict'; // 严格模式
        // demo 1:
        console.log(this);
    
        // demo 2:
        var a = this;
        console.log(a);
    
        // demo 3:
        b = this; // 注意:严格模式下,变量必须得声明;非严格模式,可以省略声明符
        console.log(b);
    
        /*
        分析:
            浏览器环境下:
    
            在整个 执行上下文 创建过程,都是在 全局执行环境下进行的,而这种由全局执行环境创建的执行上下文,又叫 “全局执行上下文”;
    
            而在 Web浏览器中,全局执行环境被认为是 window对象;
    
            结果 输出了 Window对象,也就说 this 指向了“执行上下文的环境对象”;
    
            所以,结论 “this 指向其执行上下文的环境对象”,通过;
    
         */
    </script>
    </body>
    </html>
    
    
    2.函数上下文的 this
      
      严格模式:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>this 指向</title>
    </head>
    <body>
    <script type="text/javascript">
        /*
        2.函数上下文中的 this
    
        浏览器环境下:
    
            严格模式下
         */
        // demo :
        'use strict'; // 严格模式
        var a = 1;
        // demo 1:
        function test1(){
            console.log(this);
        }
        test1();    // strict-->undefined     nostrict-->Window
    
        /*
        首先,要了解一点,函数的 this指向,有些特殊;
    
        它与全局环境中的 this 不一样,因为全局中的 this 已经明显指出了它的执行上下文环境就是 全局环境,那么它的 this 一定指向全局对象 Window;
    
        根据 《JavasScript 高级程序设计》中提到的,关于 javascript严格模式,this 指向的说明:“严格模式下,函数的 this值始终是 指定的值,无论这个指定的值是什么”;
    
        那么,我们一直是在求证我们的“this指向 其执行上下文的环境对象”,那么我们就开始试着把这个 “指定的值”理解为我们所说的 环境对象;看看在之后的论述中是否说的通;
    
        然后我们做一个这样的总结,也就是说,在严格模式下,function的环境对象是指定的;
    
        结合上面 demo在严格模式下运行的结果为 undefined来看,应该是说的通了,
    
        分析:
    
            因为 test1() 在执行的时候,并没有给它指定环境对象,所以 得出结果是 undefined;
         */
        
        /*
        下面,我们给 test1() 指定 一个环境变量后再看一下输出;
         */
        test1.call(window);    //strict-->Window     nostrict-->Window
    
        /*
        也许有人会问,window可以直接调用 test1(),并且输出 this值为 Window, 这是为什么呢? 如下:
         */
        window.test1(); // Window
        /*
        这是因为,function test1 在全局作用域下声明的,而全局作用域下声明的变量都是 window对象的方法,所以可以用这样的 对象.方法() 的形式 执行函数;
    
        而,函数作为对象方法被使用的时候,函数的执行上下文环境对象就为 这个拥有它的对象;
         */
        
        /*
        我们再给 test1() 指定其它的环境对象,看看情况是什么样的;
         */
        var obj = {name: 'obj'};
        test1.call(obj)    // {name: 'obj'}
        test1.call(null) // null
        test1.call(undefined) // undefined
        /*
        还真是 指定啥就是啥啊!
         */
        
        /*
        以上的论述 最终思想,是证明了,严格模式下,函数的 this 指向是指定的对象,即使,指定的是 null 和 undefined, this的指向也是 null 和 undefined;
    
         如果没有指定 会返回 undefined;
    
         而我们 把这个被指定的对象,来作为 test()执行上下文的环境对象,那么 我们的结论 是说的通的;
    
         概括一下:
    
            浏览器环境 严格模式下:
    
            函数作为单独函数 执行:
    
                 1.函数执行上下文的环境对象 是指定的,指定什么就是什么;this指向这个指定的环境对象;
    
            函数作为对象方法 执行:
    
                 2.这个函数执行上下文的环境对象就是这个拥有它的对象;this指向这个拥有它的对象;
         */
    </script>
    </body>
    </html>

      非严格模式:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>this 指向</title>
    </head>
    <body>
    <script type="text/javascript">
        /*
        2.函数上下文中的 this
    
        浏览器环境下:
            
            非严格模式下
         */
    
        /*
        好了,严格模式下,我们已经得出结论了; 我们再来看看非严格模式下 输出结果会是什么样;
         */
        // demo 1: 作为单独函数 执行
        // "use strict" 
    
        function test1(){
            console.log(this);
        }
        test1();                // Window
    
        test1.call(window);        // Window
    
        window.test1();            // Window
    
        var obj = {name: 'obj'};
    
        test1.call(obj)            // {name: 'obj'}
    
        test1.call(null)         // Window
    
        test1.call(undefined)     // Window
    
        // demo 2: 作为对象方法 执行
        var obj2 = {
            a:1,
            sayThis: function(){
                console.log(this);
            }
        }
        obj2.sayThis();    // obj2
    
        /*
        我们发现,原来 没有被指定执行上下文环境对象 或 指定了执行上下文环境变量为 undefined 和 null 的,它的 this 值都指向了 Window 对象;
         
        非严格模式下,我们应该可以这样下个结论,
    
        "非严格模式下,如果函数在执行时 没有指定执行上下文环境对象 或者 指定执行上下文环境对象为 null 或 undefined, 那么它的执行上下文环境对象 会默认为 全局对象",
    
        也就是 this 会指向 全局对象;
    
        概括一下:
    
            浏览器环境 非严格模式下:
        
            函数作为单独函数 执行:
    
                 1.函数执行上下文的环境对象 是指定的,指定什么就是什么;this指向这个指定的环境对象;
    
            函数作为对象方法 执行:
    
                 2.这个函数执行上下文的环境对象就是这个拥有它的对象;this指向这个拥有它的对象;
         */
    </script>
    </body>
    </html>
     
      复杂测试:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>this 指向</title>
    </head>
    <body>
    <script type="text/javascript">
        /*
        2.函数上下文中的 this
    
        浏览器环境下:
         */
        /*
        有人会说啊,你这都是在全局环境下运行的例子并且例子太简单了,然后就下结论了,这太不具备说服力了:
    
        个人一直认为,分析原理性的东西,越是从简单入手,才能越是切中要害,掌握单个知识点的精髓,复杂的分析 只是由 n多个小知识点 组合而成而已;
    
        我下面来个复杂点的,验证我们的结论;
         */
        // demo 3:
        "use strict" 
    
        var name = "sss";
        var obj = {
            name: "jjj",
            sayName: function(){
                console.log(this);
    
                innerFunction();
                function innerFunction(){
                    console.log(this);
                }
    
                return function(){
                    console.log(this);
                }
            }
        }
    
        // scene 1:
        obj.sayName();                // strict -->obj undefined    no strict -->obj window   
        /*
        分析: 
            sayName()作为 obj对象方法来执行,它的环境对象是 obj对象;
    
            innerFunction() 没有指定执行上下文的环境对象,
    
            所以,执行上下文的环境对象,严格模式下,为 undefined; 非严格模式下,为 Window对象;
    
        */
    
        // scene 2:
        obj.sayName()();            // strict -->obj undefined undefined     no strict-->obj window window
        /*
        --> 上式的执行 相当于 下面两句表达式
         */
        var test = obj.sayName();    // strict -->obj undefined     no strict-->obj window
        test();                        // strict -->undefined     no strict-->window
        /*
        分析:
             先执行 obj.sayName(), 输出结果的原因,已在 scene 1中做了说明,不再重复;
    
            执行 test(),由于 test代表 obj.sayName()执行后,返回的匿名函数,当这个匿名函数 执行时,由于没有给它指定 执行上下文的环境对象,
    
            所以,它的执行上下文环境对象,严格模式下 是 undefined; 非严格模式下 是 Window对象;
    
            输出结果,与结论相稳合;
         */
    
         // scene 3:
        test.call(obj);                // strict -->obj     no strict-->obj
        /*
        分析: 
             接着 scene 2的解释,test代表 obj.sayName()执行后,返回的匿名函数,然后又给这个函数指定了执行上下文的环境对象 obj;
    
            从输出结果来看,这符合给出的结论;
         */
    
        
        /*
        综上,浏览器环境下,我们的对 函数的执行上下文环境对象的结论概括 是成立的;
    
         */
    </script>
    </body>
    </html>
    
    

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

    4.构造函数 和 原型方法中的 this
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
    <script type="text/javascript">
    /*
        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: ƒ, constructor: ƒ}
    
        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 对象;
         */
    </script>
    </body>
    </html>
    
    

    5.应用 call、apply、bind 方法后的 this
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>this 指向</title>
    </head>
    <body>
    <script type="text/javascript">
        /*
        5.应用 call、apply、bind 方法后的 this
    
        了解:call、apply、bind 这三个方法是 Function对象才有的方法;它们的作用,主要是指定函数中 this中的指向,只是用法稍有不同;
        
        浏览器环境下:
            
            严格模式下:this指向 这三个方法所指定的这个值,无论是什么,即使是 null、undefined, this 也指向它们;
    
            非严格模式下:this指向 这三个方法所指定的这个值,null 和 undefined 值会被转换为全局对象 window;
         */
        // 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的时候, 
    
        这三个方法是经常要用到的 所以单拿出来,以作记忆吧;
         */    
    </script>
    </body>
    </html>
    
    
    
     
    原创:转载注明出处,谢谢 :)
  • 相关阅读:
    makefile中的wildcard和patsubst
    makefile中=,:=,?=,+=区别
    hash函数查找和ASL计算
    ubuntu apt-get提示no dependencys怎么办
    增广贤文是不多的古典珍宝之一
    如何打印查看c++stack<..>中的内容(不使用pop,top)
    c/c++标准IO重定向
    c/c++使用#define,#ifdef,#endif将debug代码分离
    未完待续
    c++重载覆盖重定义多态其他别名区别
  • 原文地址:https://www.cnblogs.com/cnblogs-jcy/p/8909842.html
Copyright © 2020-2023  润新知