zoukankan      html  css  js  c++  java
  • 【JavaScript】深入理解call,以及与apply、bind的区别

    一、call

    call有两个妙用

         1、继承(我前面的文章有提到用call实现call继承,有兴趣可以看下。https://www.cnblogs.com/pengshengguang/p/10547624.html

         2、修改函数运行时this的指向(今天要说的)

    // 代码段一
    var obj = {name: 'psg'};
    function fn(num1, num2) {
        console.log(num1+num2);
        console.log(this)  
    }
    // 1、call里面,第一个参数就会说要变成this的对象
    fn(100, 200); //this指向window, num1=100, num2=200
    fn.call(100, 200); //this指向100, num1=200, num2=undefined
    fn.call(obj, 100, 200); //this指向obj,  num1=100, num2=200
    
    // 2、在非严格模式下,call里面,第一个参数如果是空、null、undefined,会导致this指向window
    fn.call(); //this指向window
    
    // 3、在严格模式下,call里面,传谁this就是谁,不传,this就是undefined
    fn.call(); //this指向undefined
    fn.call(null); //this指向null
    fn.call(undefined); //this指向undefined
    

    二、apply

         1、apply和call方法的作用是一模一样的,都是用来改变方法中this关键字并且将方法执行,而且在严格模式、非严格模式下对于第一个参数是null / undefined这种情况的规律也是一样的。

         2、跟call唯一的的区别就是语法的区别:

    //call传递参数是用逗号分隔,一个一个传进去
    fn.call(obj, arg1,arg2,arg3.....)
    //apply传递参数是用一个数组传的
    fn.apply(obj, [arg1,arg2,arg3....])
    

    三、bind

         1、这个方法在IE6-IE8下不兼容。

         2、与apply、call类似,都是用来改变this指向,但是bind体现了js的预处理思想。

              ->预处理:实现把fn的this改变成我们想要的结果,并且把对象的参数也准备好了,以后要用到了,直接执行即可。

    var obj = {name: 'psg'};
    function fn(num1, num2) {
        console.log(num1+num2);
        console.log(this);
    }
    fn.call(obj, 100, 200);
    fn.bind(obj, 100, 200);  // 只是改变了fn中的this为obj,并且给fn传递了两个参数值,但是此时并没有给fn这个函数执行。
    // 但是,执行bind会有一个返回值,这个返回值myFn就是我们把fn的this改变后的那个结果!!!
    
    //那么,如何让fn这个函数执行呢,下面的写法就行解决方法
    var myFn = fn.bind(obj, 100, 200);
    myFn();
    

    四、深入理解call

      4.1 如果我们要理解call,我们首先要知道call是怎样被执行的,涉及到了原型链查找机制。

    //例如,现在有一个函数fn,我们想改变fn中this的指向,因此我们可以
    fn.call(obj);
    //上面的代码,其实是首先通过fnl的原型链,找到Function.ptototype中的call方法,然后执行call方法,cal方法中的this,就是fn
    

      4.2 伪代码模拟实现call方法

    //伪代码
    Function.prototype.myCall = function(context) {
        //->1、让fn中的this关键字变成context
        this = eval(this.toString().replace("this", context));
        //->2、让fn执行
        this();  
    }  
    

      

      4.3 经典面试题

    // 练习一
    function fn1() {console.log(1);}
    function fn2() {console.log(2);}
    fn1.call(fn2); // ->1    
    // 原理:首先fn1通过原型链机制找到Function.prototype上的call方法,并且让call方法执行
    // 此时call这个方法中的this就是fn1,在call方法执行过程中,让fn1中this关键字变成fn2,然后让fn1执行
    
    fn1.call.call(fn2); // ->2
    // 原理首先fn1通过原型链机制找到Function.prototype上的call方法,然后再让call方法通过原型找到call方法
    // Function.prototype原型上的call(因为fn.call这个东西也是个函数数据类型),在第二次找到call时,让call方法执行,此时
    // 的this是fn1.call。
    

      end

  • 相关阅读:
    Apple Swift编程语言入门教程
    网络请求错误
    Mac使用大全
    MPMovieplayerController添加新控件
    ios9 新变化
    UITableView总结
    UINavigationController的简单学习
    HTML
    谓词(NSPredicate)
    NSString字符串
  • 原文地址:https://www.cnblogs.com/pengshengguang/p/11184378.html
Copyright © 2011-2022 走看看