您现在的位置:首页 >> 前端 >> 内容

call()、apply()、bind()详解

时间:2017/3/27 9:55:00 点击:

  核心提示:call()、apply()、bind()详解,在 JavaScript 中,this 是指当前函数中正在执行的上下文环境;当你调用一个函数时,this总是作为一个(隐式)参数。(1)、宽松模式下的普...

call()、apply()、bind()详解,在 JavaScript 中,this 是指当前函数中正在执行的上下文环境;当你调用一个函数时,this总是作为一个(隐式)参数。

(1)、宽松模式下的普通函数:
this总是指向全局对象,(在浏览器中是window)

var a=123;
var A=function(){
   return this;  //Window 
}

(2)、严格模式下
使用严格模式,只需要将 ‘use strict’ 置于函数体的顶部。this总是undefined;

var a=123;
var A=function(){
   'use strict';
    return this;   //undefined
}

(3)方法
this指向调用方法的对象

  var qwe={
       method:function(){
           return this;
       }
   }
  console.log(qwe.method()===qwe) ;   //true

在讲call()之前先说一下,函数调用有4中类型:

函数调用 alert('Hello World!')

方法调用 console.log('Hello World!')

构造函数调用 new RegExp('\\d')

间接调用 alert.call(undefined, 'Hello World')

注意:this 是指当前函数中正在执行的上下文环境

陷阱:this 在内部函数中

一个常见的陷阱是理所应当的认为函数调用中的,内部函数中 this 等同于它的外部函数中的 this。

正确的理解是内部函数的上下文环境取决于调用环境,而不是外部函数的上下文环境。

为了获取到所期望的 this,应该利用间接调用修改内部函数的上下文环境,如使用 .call() 或者 .apply或者创建一个绑定函数 .bind()。

利用call、apply、bind这三个方法,可以改变this的指向,使它指向我们期望的对象。

一、call()

关于javascript中的call方法,总结网上的观点,call有两个妙用:

1: 修改函数运行时的this指针。

2: 继承。(不太喜欢这种继承方式。)

简单说明一下

var f=function(){}
f.call(o)

解释:一个简单的例子,在全局环境下创建一个变量f,在函数f里面的this指向全局,window;但是利用call方法,将this指向了对象o,在o的作用域中运行函数f。

1、call()的完整使用格式:

func.call(thisValue, arg1, arg2, ...)

第一个参数是this要重新指向的那个对象,后面的参数是调用时所需要的参数;

或者是:

Function.prototype.call(thisValue, arg1, arg2, ...)

说明 :
call 方法可以用来代替另一个对象调用一个方法。

obj1.method1.call(obj2,argument1,argument2)
如上,call的作用就是把obj1的方法method1放到obj2上使用,后面的argument1..这些做为参数传入。

简单例子如下:

   function one1(a,b){
        console.log(a+b);
    };
   function two1(a,b){
       console.log(a-b);
   };
   one1.call(two1,5,2);     //7

这个例子中的意思就是用 one1来替换 two1,所以运行结果为:7
// 注意:js 中的函数其实是对象,函数名是对 Function 对象的引用。

看个稍微复杂的例子:

   function duixiang1(){
       this.name="zyy";
       this.method=function(){
           return this.name;
       }
   };
   function duixiang2(){
       this.name="zxd";
   }
   var q1=new duixiang1();
   var q2=new duixiang2();
   console.log(q1.method());         //zyy
   console.log(q1.method.call(q2));  //zxd

解释:call 的意思是把 q1的方法放到q2上执行,原来q2是没有method() 方法,现在是把q1 的method()方法放到 q2 上来执行,所以this.name 应该是 zxd,执行的结果就是 :zxd;

有意思吧,可以让a对象来执行b对象的方法。还有更有趣的,可以用 call 来实现继承 :

接下来说明一下call()实现继承:

    function Class1(){
        this.name="abc";
        this.method=function(a){
            console.log("这是Class1的参数"+a);
        }
    };
    function Class2(){
        Class1.call(this);
       // this.name="qwe"
    }
    var newclass2=new Class2();
    newclass2.method("asd");   //这是Class1的参数asd

这样 Class2 就继承Class1了,Class1.call(this) 的 意思就是使用 this对象代替Class1对象调用Class1的方法,那么 Class2 中不就有Class1 的所有属性和方法了吗,Class1对象就能够直接调用Class1 的方法以及属性了,执行结果就是:alert(“cc”);

对的,就是这样,这就是 javascript 如何来模拟面向对象中的继承的,还可以实现多重继承。

    function Ff1(){
        this.methodadd=function(a,b){
            console.log(a+b)
        }
    };
    function Ff2(){
        this.methodjian=function(a,b){
            console.log(a-b);
        }
    };
    function Ff3(){
        Ff1.call(this);
        Ff2.call(this);
    };
    var shili=new Ff3();
    shili.methodadd(2,2);  //4
    shili.methodjian(5,4); //1

很简单,使用两个 call 就实现多重继承了 。

Tags:CA AL LL L、 
作者:网络 来源:不详