zoukankan      html  css  js  c++  java
  • 245 改变函数内部 this 指向:call,apply,bind,call、apply、bind 三者的异同

    2.2.1 call方法

    call()方法调用一个对象,简单理解为调用函数的方式,但是它可以改变函数的 this 指向

    应用场景: 经常做继承。

    var o = {
    	name: 'andy'
    }
     function fn(a, b) {
          console.log(this);
          console.log(a+b)
    };
    fn(1,2)  // 此时的this指向的是window 运行结果为3
    fn.call(o,1,2)  //此时的this指向的是对象o, 参数使用逗号隔开, 运行结果为3
    

    以上代码运行结果为:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <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); // 3
            };
            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) {
                // 不需要加 new ,不用new Father
                Father.call(this, uname, age, sex);
            }
    
            var son = new Son('刘德华', 18, '男');
            console.log(son);
        </script>
    </body>
    
    </html>
    

    2.2.2 apply方法

    apply() 方法调用一个函数。简单理解为调用函数的方式,但是它可以改变函数的 this 指向。

    应用场景: 经常跟数组有关系

    var o = {
    	name: 'andy'
    }
     function fn(a, b) {
          console.log(this);
          console.log(a+b)
    };
    fn()// 此时的this指向的是window 运行结果为3
    fn.apply(o,[1,2])//此时的this指向的是对象o,参数使用数组传递 运行结果为3
    

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    
    <body>
        <script>
            // 改变函数内this指向  js提供了三种方法  call()  apply()  bind()
    
            // 2. apply()  应用 运用的意思
            var o = {
                name: 'andy'
            };
    
            function fn(arr) {
                // console.log(this);
                console.log(arr);
            };
    
            var arr = [1, 66, 3, 99];
            var arr1 = ['green', 'red', 'blue'];
    
            fn.apply(o, [1, 66, 3, 99]); // (1) 1; (2) 相当于fn(1, 66, 3, 99)
            fn.apply(o, ['green', 'red', 'blue']); // (1) green; (2) 相当于fn('green', 'red', 'blue')
    
            fn.apply(o, [[1, 66, 3, 99]]); // (1) [1, 66, 3, 99]; (2) 相当于fn([1, 66, 3, 99])
    
            fn.apply(o, [['green', 'red', 'blue']]); // (1) ['green', 'red', 'blue']; (2) 相当于fn(['green', 'red', 'blue'])
    
            // 1. 也是调用函数,第二个可以改变函数内部的this指向
            // 2. 但是它的参数必须是数组(伪数组)
            // 3. apply 的主要应用, 比如说我们可以利用 apply 借助于数学内置对象求数组最大值 
    
    
            // var max = Math.max.apply(null, arr);
            var max = Math.max.apply(Math, arr);
            var min = Math.min.apply(Math, arr);
            console.log(max, min); // 99 1
        </script>
    </body>
    
    </html>
    

    2.2.3 bind方法

    bind() 方法不会调用函数,但是能改变函数内部this 指向,返回的是原函数改变this之后产生的新函数。

    如果只是想改变 this 指向,并且不想调用这个函数的时候,可以使用bind。

    应用场景:不调用函数,但是还想改变this指向。

     var o = {
     name: 'andy'
     };
    
    function fn(a, b) {
    	console.log(this);
    	console.log(a + b);
    };
    var f = fn.bind(o, 1, 2); //此处的f是bind返回的新函数
    f();//调用新函数  this指向的是对象o 参数使用逗号隔开
    

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <style>
            /* 禁用按钮的效果看的更明显 */
            button {
                /* background-color: lightcyan; */
                font-size: 20px;
                font-weight: 700;
                /* color: orangered; */
            }
        </style>
    </head>
    
    <body>
        <button>点击</button>
        <button>点击</button>
        <button>点击</button>
        <script>
            // 改变函数内this指向  js提供了三种方法  call()  apply()  bind()
    
            // 3. bind()  绑定 捆绑的意思
            var o = {
                name: 'andy'
            };
    
            function fn(a, b) {
                console.log(this);
                console.log(a + b);
            };
            var f = fn.bind(o, 1, 2); // (1)3;(2)如果这里传参了,就以这里的参数为准;如果这里没传参,就以调用f时的参数为准。
            f();
    
            // 1. 不会调用原来的函数,可以改变原来函数内部的this 指向
            // 2. 返回的是原函数改变this之后产生的新函数。
            // 3. 如果有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向,此时用bind
    
            // 4. 我们有一个按钮,当我们点击了之后,  就禁用这个按钮, 3秒钟之后开启这个按钮
    
            // var btn1 = document.querySelector('button');
            // btn1.onclick = function() {
            //     this.disabled = true; // 这个this 指向的是 btn 这个按钮
            //     // var that = this;
            //     setTimeout(function() {
            //         // that.disabled = false; // 定时器函数里面的this 指向的是window
            //         this.disabled = false; // 此时定时器函数里面的this 指向的是btn
            //     }.bind(this), 3000); //  bind(this) 的 this 在定时器函数的外面,所以这个this 指向的是btn 这个对象
            // }
    
    
            var btns = document.querySelectorAll('button');
            for (var i = 0; i < btns.length; i++) {
                btns[i].onclick = function() {
                    this.disabled = true;
                    setTimeout(function() {
                        this.disabled = false;
                    }.bind(this), 2000); //
                }
            }
        </script>
    </body>
    
    </html>
    


    2.2.4 call、apply、bind三者的异同

    • 共同点 : 都可以改变this指向

    • 不同点:

      • call 和 apply 会调用函数, 并且改变函数内部this指向.
      • call 和 apply传递的参数不一样,call传递参数使用逗号隔开,apply使用数组传递
      • bind 不会调用函数, 可以改变函数内部this指向.
    • 应用场景

      1. call 经常做继承.
      2. apply经常跟数组有关系. 比如借助于数学对象实现数组最大值最小值
      3. bind 不调用函数,但是还想改变this指向. 比如改变定时器内部的this指向.
  • 相关阅读:
    Truck History(poj 1789)
    Highways poj 2485
    117. Populating Next Right Pointers in Each Node II
    116. Populating Next Right Pointers in Each Node
    115. Distinct Subsequences
    114. Flatten Binary Tree to Linked List
    113. Path Sum II
    109. Convert Sorted List to Binary Search Tree
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
  • 原文地址:https://www.cnblogs.com/jianjie/p/12230204.html
Copyright © 2011-2022 走看看