美文网首页
JavaScript - this与函数的四种调用方式

JavaScript - this与函数的四种调用方式

作者: Hyso | 来源:发表于2019-04-09 11:45 被阅读0次

在 ES6 之前,函数内部 this 的指向是由该函数的调用方式来决定的

函数调用方式

使用函数调用方式调用函数时,函数内部的 this 指向 window 对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</style>
</style>
</head>
<body>
    <script>
        var name = 'Tom';
        function fn() {
           console.log(this.name);
        }
            
        // Tom
        fn();
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</style>
</style>
</head>
<body>
    <script>
        var age = 18;
        var Person = {
            age:15,
            say:function() {
               console.log(this.age); 
           }
        }
            
        var f = Person.say;
        // 18
        f();
    </script>
</body>
</html>

方法调用方式

使用方法调用方式调用函数时,函数内部的 this 指向调用该函数的对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div class="box">
        <img src="photo.jpg" alt="" />
        <span class="tag">标签<i></i></span>
    </div>
    <script>
        function Person() {
            this.name = 'Tom';
        }

        Person.prototype.run = function() {
            console.log(this.name);
        }

        var p = new Person();
        // Tom,this 指向调用该函数的对象 p
        p.run();
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div class="box">
        <img src="photo.jpg" alt="" />
        <span class="tag">标签<i></i></span>
    </div>
    <script>
        var length = 50;
        var getLength = function() {
            console.log(this.length);
        }

        var t = {g:getLength, length:100};
        // 100,this 指向调用该函数的对象 t
        t.g();
    </script>
</body>
</html>

构造函数调用方式

使用构造函数调用方式调用函数时,函数内部的 this 指向调用该函数的实例对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</style>
</style>
</head>
<body>
    <script>
        function Person() {
            this.name = 'Tom';
        }

        Person.prototype.say = function() {
            console.log(this.name);
        }

        var p = new Person();
        // Tom,this 指向实例对象 p
        p.say();
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</style>
</style>
</head>
<body>
    <script>
        function Jquery() {
            var _init = Jquery.prototype.init;

            var o = new _init();
            return o;
        }

        Jquery.prototype = {
            constructor:Jquery,
            length:100,
            init:function() {
                // 1. 首先查看本身有没有 length 属性
                // 2. 如果没有,则去它的原型对象中查找
                // 3. 如果原型对象中没有,则去它的原型对象的原型对象中查找,最终一直找到根对象(Object.prototype)
                // 4. 最终没有找到的话,则表示该对象中没有该属性,获取一个对象中某个不存在的属性时,该属性的值为 undefined
                console.log(this.length);
            }
         }

         // 输出:undefined
        Jquery();
    </script>
</body>
</html>

上下文调用方式

  • call 方法和 apply 方法的第一个参数决定了函数内部 this 的指向
    1)如果第一参数是对象类型,那么函数内部的 this 指向该对象
    2)如果第一参数是 null、undefined,那么函数内部的 this 指向 window 对象
    3)如果第一参数是数字,那么函数内部的 this 指向 Number 构造函数的实例
    4)如果第一参数是字符串,那么函数内部的 this 指向 String 构造函数的实例
    5)如果第一参数是布尔值,那么函数内部的 this 指向 Boolean 构造函数的实例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</style>
</style>
</head>
<body>
    <script>
        function fn() {
            console.log(this);
        }

        // (3) [1, 3, 5]
        fn.call([1, 3, 5]);
        // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
        fn.call(null);
        // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
        fn.call(undefined);
        // Number {1}
        fn.call(1);
        // String {"abc"}
        fn.call("abc");
        // Boolean {true}
        fn.call(true);

        // (3) [1, 3, 5]
        fn.apply([1, 3, 5]);
        // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
        fn.apply(null);
        // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
        fn.apply(undefined);
        // Number {1}
        fn.apply(1);
        // String {"abc"}
        fn.apply("abc");
        // Boolean {true}
        fn.apply(true);
    </script>
</body>
</html>

call 方法和 apply 方法的不同之处:传参的形式不同

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</style>
</style>
</head>
<body>
    <script>
        function getString(a, b, c) {
            console.log(a+" "+b +" "+c);
        }

        // 1 3 5
        getString.call(null, 1, 3, 5);
        
        // 1 3 5
        getString.apply(null, [1, 3, 5]);
    </script>
</body>
</html>
  • bind 方法
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</style>
</style>
</head>
<body>
    <script>
        var obj1 = {
            age:18,
            run:function() {
                setTimeout(function() {
                    console.log(this.age);
                }, 50);
            }
        }

        // setTimeout 是由 window 调用的,所以输出 undefined
        obj1.run();

        var obj2 = {
            age:18,
            run:function() {
                setTimeout((function() {
                    console.log(this.age);
                }).bind(this), 50);
            }
        }

        // 通过执行bind方法,将匿名函数内部 this 指向 obj2 对象,所以输出 18
        obj2.run();

        function speed() {
            console.log(this.seconds);
        }

        // 通过执行bind方法,将 speed 函数内部 this 指向 {seconds:100} 对象
        var speedBind = speed.bind({seconds:100});
        // 100
        speedBind();

        // 以上代码通常优化为:
        (function speed() {
            console.log(this.seconds);
        }).bind({seconds:100})();
    </script>
</body>
</html>

相关文章

网友评论

      本文标题:JavaScript - this与函数的四种调用方式

      本文链接:https://www.haomeiwen.com/subject/oyhuiqtx.html