JavaScript高級教程(21)——函數的this指向、call()、apply()、bind()

1.函數的定義和調用

1.1函數的定義方式

1.函數聲明方式function關鍵字(命名函數)
2.函數表達式(匿名函數)
3.new Function()
在這裏插入圖片描述
注意:(1)Function()裏面參數必須是字符串格式;(2)第三種方式執行效率低,也不方便書寫,因此較少使用;(3)所有函數都是Function的實例(對象);(4)函數也屬於對象

在這裏插入圖片描述

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        //函數的定義方式
        //1.自定義函數(命名函數)
        function fn() {};
        //2.函數表達式(匿名函數)
        var fun = function() {};
        //3.利用new Function('參數1', '參數2', '參數3')
        var f = new Function('a', 'b', 'console.log(a + b)');
        f(1, 2);
        console.dir(f);
        console.log(f instanceof Object); //true
    </script>
</body>

</html>

1.2函數的調用方式

1.普通函數
2.對象的方法
3.構造函數
4.綁定事件函數
5.定時器函數
6.立即執行函數

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button>點擊</button>
    <script>
        var btn = document.querySelector('button');
        //函數的調用方式
        //1.普通函數
        function fn() {
            console.log(1);
        }
        // fn();
        // fn.call();
        //2.對象的方法
        // var o = {
        //     sayHi: function() {
        //         console.log(11);

        //     }
        // }
        // o.sayHi();
        //3.構造函數
        function Star() {
            console.log(22);

        };
        new Star();
        //4.綁定事件函數
        btn.onclick = function() {
            console.log(33);
        };
        //5.定時器函數
        setInterval(function() {}, 1000); //定時器1秒調用一次
        //6.立即執行函數
        (function() {
            console.log(44);

        })()
        //立即執行函數是自動調用
    </script>
</body>

</html>

2.this

2.1函數內this的指向

這些this的指向,是當我們調用函數的時候確定的。調用方式的不同決定了this的指向不同,一般指向我們的調用者
在這裏插入圖片描述

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button>點擊</button>
    <script>
        var btn = document.querySelector('button');
        //函數的調用方式
        //1.普通函數  this指向window
        function fn() {
            console.log('普通函數的this' + this);
        }
        fn();
        // fn();
        // fn.call();
        //2.對象的方法  this指向的是對象 o
        var o = {
            sayHi: function() {
                console.log('對象方法的this:' + this);

            }
        }
        o.sayHi();
        //3.構造函數  this指向ldh這個實例對象  原型對象裏面的this指向的也是ldh這個實例對象
        function Star() {
            console.log(22);

        };
        Star.prototype.sing = function() {}
        var ldh = new Star();
        //4.綁定事件函數  this 指向的是函數的調用者  btn這個按鈕
        btn.onclick = function() {
            console.log('綁定函數的this:' + this);
        };
        //5.定時器函數  this指向的也是window
        setInterval(function() {
            console.log('定時器的this:' + this);

        }, 1000); //定時器1秒調用一次
        //6.立即執行函數  this  指向的是window
        (function() {
            console.log('立即執行函數的this:' + this);

        })()
        //立即執行函數是自動調用
    </script>
</body>

</html>

2.2改變函數內部this指向

JavaScript爲我們專門提供了一些函數方法來幫我們更優雅的處理內部this的指向問題,常用的有bind()、call()、apply()三種方法。

1.call方法

call()方法調用一個對象。簡單理解爲調用函數的方式,但是它可以改變函數的this指向。
在這裏插入圖片描述

  • thisArg:在fun函數運行時指定的this值
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        //改變函數this指向  js提供了三種方法  call() apply() bind()
        //1.call()
        var o = {
            name: 'andy'
        }

        function fn(a, b) {
            console.log(this);
            console.log(a + b);

        };
        fn.call(o, 1, 2);
        //call  第一個可以用來調用函數 第二個可以改變函數內this指向
        //call 的主要作用可以實現繼承
        function Father(uname, age, sex) {
            this.uname = uname;
            this.age = age;
            this.sex = sex;
        }

        function Son(uname, age, sex) {
            Father.call(this, uname, age, sex);
        }
        var son = new Son('張三', 18, '男');
        console.log(son);
    </script>
</body>

</html>

2.apply方法

apply()方法調用一個函數。簡單理解爲調用函數的方式,但是它可以改變函數的this指向。
在這裏插入圖片描述

  • thisArg:在fun函數運行時指定的this值
  • argsArray:傳遞的值,必須包含在數組裏面
  • 返回值就是函數的返回值,因爲它就是調用函數
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        //2.apply()  應用  運用的意思
        var o = {
            name: 'andy'
        };

        function fn(arr) {
            console.log(this);
            console.log(arr); //打印出來的是字符串

        };
        fn.apply(o, ['pink']);
        //1.也是調用函數  第二個可以改變函數內部的this指向
        //2.但是他的參數必須是數組(僞數組)
        //3.apply的主要運用  比如說我們可以利用apply 藉助於數學內置對象求最大值
        var arr = [1, 66, 3, 99, 4];
        var max = Math.max.apply(Math, arr);
        var min = Math.min.apply(Math, arr);
        console.log(max);
        console.log(min);
    </script>
</body>

</html>

3.bind方法

bind()方法不會調用函數,但是能改變函數內部this指向
在這裏插入圖片描述

  • thisArg:在fun函數運行時指定的this值
  • arg1, arg2:傳遞的其他參數
  • 返回由指定的this值和初始化參數改造的原函數拷貝
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button>點擊</button>
    <script>
        //bind() 綁定 捆綁的意思
        var o = {
            name: 'andy'
        };

        function fn(a, b) {
            console.log(this);
            console.log(a + b);

        };
        var f = fn.bind(o, 1, 2);
        f();
        //1.不會調用原來的函數  可以改變原來函數內部的this指向
        //2.返回的是原函數改變this之後產生的新函數
        //3.如果有的函數我們不需要立即調用  但是又想改變這個函數內部的this指向此時用bind
        //4.我們有一個按鈕,當我們點擊了之後,就禁用這個按鈕,3秒鐘之後開啓這個按鈕
        var btn = document.querySelector('button');
        btn.onclick = function() {
            this.disabled = true; //this指向btn
            setTimeout(function() {
                this.disabled = false; //定時器裏面的this指向的是window
            }.bind(this), 3000); //這個this指向的是btn這個對象
        }
    </script>
</body>

</html>

2.3call apply bind 總結

相同點:
都可以改變函數內部指向

區別點:
1.call和apply會調用函數,並且改變函數內部this指向
2.call和apply傳遞的參數不一樣,call傳遞參數aru1, aru2…形式,apply必須數組形式[arg]
3.bind不會調用函數,可以改變函數內部this指向

主要應用場景:
1.call經常做繼承
2.apply經常跟數組有關係,比如藉助於數學對象實現數組最大值最小值
3.bind不調用函數,但是還想改變this指向,比如改變定時器內部的this指向

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章