天天看點

Javascript - 函數分類 & this指向

Javascript - 函數分類 & this指向

Javascript中定義函數的三種方式,通過執行個體來說明吧。

<script>
        //method1
        function fn() {
            console.log('fn created ');
        }
        //method2
var fn2 = function () {
            console.log('fn2 created');
        }
        //method3
var fn3 = new Function('test', 'console.log(test);');
        fn3('fn3 test');
        console.dir(fn3);
        console.log(fn3 instanceof Object);
</script>      

運作上面例子,證明了函數也是對象。可以采用new + 構造函數的方式建立執行個體,第三種方式執行效率低。

函數的原型鍊

Javascript - 函數分類 &amp; this指向

從結果可以看到Function原型對象的__proto__指向Object。

Javascript - 函數分類 &amp; this指向

js中函數的分類和調用方式。

通過執行個體來說明吧。

<script>
        //函數的分類和調用方式
        //方式1 普通标準函數,this 指向window
        function fn() {
            console.log('fn1'+ this);
        }
        fn(); //本質是window.fn(); 全局函數是window的成員      
        //方式2 對象的方法 this 指向調用者o
        var o = {
            sayHi: function () {
                console.log('fn2'+this);
            }
        }
        o.sayHi();


        //方式3 構造函數 this指向新建立的對象,這裡指向star1
        function Star(username){
            this.username = username;
        }
        var star1 = new Star('ldh');


        //方式4 綁定事件函數 this 指向函數的調用者 btn
        var fn = function (){
            console.log('btn 被點選了'+ this);
        }
        btn.onclick = fn;
        //點選了按鈕就可以調用函數


        //方式5 定時器函數 定時器實際是window成員 是以this 就是window
        setInterval(function(){},1000);
        //定時器按照設定的時間間隔去調用


        //方式6 立即執行函數 this 是window 同方式一


        (function(){console.log('function executed')})();
//不需要調用立即執行     
</script>      

通過上面的例子,基本上歸納了筆者了解的函數使用方式。通過方式4和方式6的對比,

我們可以知道函數後面加了() 表示立即調用,沒加(),表示函數的指針,隻是指明函數不調用函數。

this 指向問題,牢記this指向調用者

改變this 指向的三個函數

this 指向是JS中很重要的問題,在上面的函數分類中,已經有了系統的分析。下面重點總結改變this 指向的三個函數。

call

把父類執行個體改成子類執行個體 實作屬性繼承。

<script>
        //call function
        function Father(username, age) {
            this.username = username;
            this.age = age;
        }


        function Son(username, age, gender) {
            Father.call(this, username, age);//實作繼承父類的屬性
            this.gender = gender;
        }
</script>      

apply

apply 和call 不同點,參數是數組(僞數組)。在apply内部會把數組拆成元素

主要使用 借助Math對象,Math.max.apply(Math, [4324, 45, 342, 23])

<script>
        //apply function
        var o = {
            username: 'testuser'
        };
        function fn(arr) {
            console.log(arr);
            for (let i = 0; i < arr.length; i++) {
                console.log(arr[i]);


            }
            console.log(this);
        }


        fn.apply(o, [23, 43]);
        console.log(Math.max(43, 45, 243, 342));
        console.log(Math.max.apply(Math, [4324, 45, 342, 23]));
</script>      

bind

隻改變this 的指向 不調用函數。

<body>
    <button>click me</button>
    <button>click me</button>
    <button>click me</button>
    <script>
        //bind function
        //案例:實作多個按鈕發送驗證碼後 3s 可以再次發送
        var btns = document.querySelectorAll('button');
        for (let i = 0; i < btns.length; i++) {
            btns[i].onclick = function () {
                this.disabled = true;
                setTimeout(function () {
                    this.disabled = false;//改變this 指向btn ,3000ms 後執行
                }.bind(this), 3000);
            }
        }       
</script>
</body>