• js中this指向学习总结


     

    在面向对象的语言中(例如Java,C#等),this 含义是明确且具体的,即指向当前对象。一般在编译期绑定。 
    然而js中this 是在运行期进行绑定的,这是js中this 关键字具备多重含义的本质原因。下面就让我们一起来分析一下具体情况。 
    由于js中this 是在运行期进行绑定的,所以js中的 this 可以是全局对象、当前对象或者任意对象,这完全取决于函数的调用方式。JavaScript 中函数的调用有以下几种方式:

    • 作为对象方法调用
    • 作为函数调用
    • 作为构造函数调用
    • 使用 apply 或 call 调用

    JavaScript this决策树

    JavaScript this决策树 
    根据这个决策树我们需要进行两步判断: 
    1.函数调用是用new进行调用的吗?如果是,则this指向新创建的对象,否则,进入”否”分支; 
    2.判断该函数是否是用dot(.)进行调用的,如果是,则即进入”是”分支,即this指向dot(.)之前的对象;否则this指向全局对象window. 
    demo1:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>this指向</title>
    </head>
    <body>
        <script type="text/javascript">
            function test(a){
                this.a = a;//相当于window.a
            }
            test(3);//这里相当于window.test(3)
            //所以test函数中的this指向了window
            console.log(a);//3  这里相当于与访问window.a
        </script>
    </body>
    </html>

    demo2: 
    对于say方法中的sayA和sayB中的this来说:不是通过new操作符来调用的,也没有通过dot(.)来调用,因此this指向window

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>this指向</title>
    </head>
    <body>
    <script type="text/javascript">
        var obj = {
            a:0,
            b:0,
            say:function(a,b){
                var sayA = function(a){
                    console.log(this);//Window
                    this.a = a;
                };
                var sayB = function(b){
                    console.log(this);//Window
                    this.b = b;
                };
                sayA(a);
                sayB(b);
            }
        }
        obj.say(1,1);
        console.log(obj.a+"--"+obj.b);//0--0
        console.log(window.a+"-----"+window.b);//1-----1
    </script>
    </body>
    </html>

    demo3:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>面试题</title>
    </head>
    <body>
    <script type="text/javascript">
        function Person(name,age){
            this.name = name;
            this.age = age;
        }
        var person1 = new Person("lisi",18);
        console.log(person1.name);//lisi
        var person2 = Person("wangwu",12);
        //person2是undefined
        // console.log(person2.name);//Uncaught TypeError: Cannot read property 'name' of undefined
        console.log(window.name);//wangwu
        //Person("wangwu",12)相当于window.Person("wangwu",12)
    </script>
    </body>
    </html>

    demo4: 
    apply 和 call 这两个方法切换函数执行的上下文环境(context),即可以改变this指向。obj1.say.call(obj2,3,3)实际上是obj2.say(3,3),所以say中的this就指向了obj2

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>this指向</title>
    </head>
    <body>
    <script type="text/javascript">
        function Test(a,b){
            this.a = a;
            this.b = b;
            this.say = function(a,b){
                this.a = a;
                this.b = b;
            }
        }
        var obj1 = new Test(1,1);
        var obj2 = {a:2,b:2};
        obj1.say.call(obj2,3,3);
        console.log(obj2.a+"--"+obj2.b);//3--3
    </script>
    </body>
    </html>

    demo5: 
    this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象.当然这句话不完全准确,因为在不同环境下情况就会有不同。下面我们就来分析一下各种情况。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>this指向</title>
    </head>
    <body>
    <script type="text/javascript">
        // 这里的函数test实际是被Window对象调用的
        function test(){
            var name = "lisi";
            console.log(this.name);//undefined
            console.log(this);//Window
        }
        test();//这里相当于window.test();
    </script>
    </body>
    </html>

    demo6: 
    如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。 
    这个例子就是指向上一级对象obj

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>this指向</title>
    </head>
    <body>
    <script type="text/javascript">
         var obj = {
            name:"lisi",
            sayName:function(){
                console.log(this.name);//lisi
            }
         }
         obj.sayName();
    </script>
    </body>
    </html>

    demo7: 
    对象字面量obj={} 
    变量obj其实也是window对象的属性 
    所以可以这样来调用window.obj.sayName(); 
    如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象,这里this指向obj,而不是window

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>this指向</title>
    </head>
    <body>
    <script type="text/javascript">
        var name = "wangwu";
         var obj = {
            name:"lisi",
            sayName:function(){
                console.log(this.name);//lisi
            }
         }
         window.obj.sayName();
    </script>
    </body>
    </html>

    demo8: 
    如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>this指向</title>
    </head>
    <body>
    <script type="text/javascript">
         var obj = {
            name:"wangwu",
            objInner:{
                name:"lisi",
                sayName:function(){
                console.log(this.name);//lisi
                }
            }
         }
         obj.objInner.sayName();
    </script>
    </body>
    </html>

    demo9: 
    尽管对象objInner中没有属性name,这个this指向的也是对象objInner,因为this只会指向它的上一级对象,不管这个对象中有没有this要的东西。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>this指向</title>
    </head>
    <body>
    <script type="text/javascript">
         var obj = {
            name:"wangwu",
            objInner:{
                // name:"lisi",
                sayName:function(){
                console.log(this.name);//undefined
                }
            }
         }
         obj.objInner.sayName();
    </script>
    </body>
    </html>

    demo10: 
    从这个例子我们可以看出:this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的 
    在这个例子中虽然函数sayName是被对象objInner所引用,但是在将sayName赋值给变量fn的时候并没有执行,所以this最终指向的是window对象。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>this指向</title>
    </head>
    <body>
    <script type="text/javascript">
         var obj = {
            name:"wangwu",
            objInner:{
                name:"lisi",
                sayName:function(){
                console.log(this.name);//undefined
                console.log(this);//Window
                }
            }
         }
         var fn = obj.objInner.sayName;
         fn();
    </script>
    </body>
    </html>

    demo11: 
    对象person可以点出构造函数中的name是因为new关键字可以改变this的指向,将这个this指向对象person. 
    这里new Person()创建了一个Person对象的实例,并赋值给了变量person

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>构造函数版this</title>
    </head>
    <body>
    <script type="text/javascript">
        function Person(){
            this.name = "lisi";
        }
        var person = new Person();
        console.log(person.name);//lisi
    </script>
    </body>
    </html>

    demo12:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>当this碰到return</title>
    </head>
    <body>
        <script type="text/javascript">
        /*
        如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例
         */
            function fn2(){
                this.username = "lisi";
                return {};
            }
            var obj = new fn2;
            console.log(obj);//Object{}
            console.log(obj.username);//undefined
            function fn1(){
                this.username = '王五';
                return function(){};
            }
            var b = new fn1;
            console.log(b);//function(){}
            console.log(b.username);//undefined
            function fn()
            {
                this.username = '王五';
                return 1;
                // return undefined;
            }
            var a = new fn;
            console.log(a);//fn {username: "王五"}
            console.log(a.username); //王五
            //虽然null也是对象,但是在这里this还是指向那个函数的实例,因为null比较特殊
            function fn3()
            {
                this.username = '王五';
                return null;
            }
            var a = new fn;
            console.log(a);//fn {username: "王五"}
            console.log(a.username); //王五
        </script>
    </body>
    </html>
  • 相关阅读:
    set
    皮肤病药物
    C 批量保存图片进 mysql 利用MYSQL_BIND插入longblob
    eclipse行号显示
    dynamic_cast使用
    list添加删除操作
    VS2008 对齐代码
    c++ mysql二进制存取,blob存取
    Select Window关键字——模拟打开了多个页面窗口时,在不同的窗口之间,进行窗口切换
    Click Image关键字——模拟单击某一个图片 其余:Click Button / Click Link
  • 原文地址:https://www.cnblogs.com/gluncle/p/8486912.html
Copyright © 2020-2023  润新知