js中的apply()和call()执行域转换详解

页面导航:首页 > 网络编程 > JavaScript > js中的apply()和call()执行域转换详解

js中的apply()和call()执行域转换详解

来源: 作者: 时间:2016-01-19 18:32 【

js中函数其实是一个对象,这两个方法都是针对函数对象的,其目的是转换当前函数的执行环境,也就是函数中this所指的对象。我们首先来看第一个实例: function A(){ B call

js中函数其实是一个对象,这两个方法都是针对函数对象的,其目的是转换当前函数的执行环境,也就是函数中this所指的对象。

我们首先来看第一个实例:

 function A(){        
        B.call(this);
    }
    function B(){
        this.show = function(){
            alert(this.param);
        }
    }
    A.prototype = {
        param : A
    }
    B.prototype = {
        param : B
    }
    var a = new A();
    a.show(); //输出A
    var b = new B();
    b.show(); //输出B

从以上实例可以看出B.call(this)这句使得函数A继承了B(B中的show()函数不在B的prototype中,但为什么b.show()可以访问不得而知,望高手赐教),而且a.show()输出A说明B.call(this)使得show函数执行时的作用域变成了对象a,所以此时访问的是对象a中prototype的param。

 

下面我们看第二个实例:

 

function A(){
  	this.param = 'A';        
        B.call(this);
    }
    function B(){
        this.show = function(){
            alert(this.param);
        }
    }
    B.prototype = {
        param : B
    }
    var a = new A();
    a.show(); //输出A
    var b = new B();
    b.show(); //输出B
    alert(A.param); //输出undefined

上述实例中我们不再在prototype对象中定义param变量,而在function A()中用this.param='A'代替,此时a.show()也能输出'A',而A.show()却输出了'undefined',这是为什么呢?首先通过之前的学习可以确定,JS中的函数是一个对象,函数名是一个函数对象的引用,而且JS中的对象和JAVA中的对象一样,同样有类和实例对象之说。于是笔者在此大胆猜测,函数里面定义的变量和prototype中定义的变量需要经过new出的对象才能直接引用,看之前我转载的一篇文章( JS中prototype详解 )中有介绍,称为“对象变量方法”和“原型变量方法”,与之相似的还有一个“类变量方法”。我们先掌握这个,对后面理解有好处。

 

下面我们看第三个实例:

 

function A(){    
        B.call(this);
    }
    function B(){
        this.newParam = 'newB';
        this.show = function(){
            alert(this.param);
        }
    }
    B.prototype = {
        param : B
    }
    var a = new A();
    a.show(); //输出undefined
    alert(a.newParam); //输出newB
    var b = new B(); 
    b.show(); //输出B
    alert(A.param); //输出undefined

上述例子中A()中去掉了this.param='A',此时a.show()输出undefined,于是可以推测出B.call(this)不会将prototype中定义的原型变量“复制”到实例变量a,如果变量不存在则输出undefined,如果方法不存在则报错,但是B()中定义的对象变量方法则可以“复制”到a变量中。注意,此处的“复制”还真是把b中的变量和方法复制到了a变量中,具体读者可用console.log()在控制台中看看。

 

下面我们看第四个实例:

 

function A(){    
       this.param = 'newA';
    }
    function B(){
    	this.newParam = 'newB';
        this.show = function(){
            alert(this.param);
        }
    }
    B.staticParam = 'staticB'; 
    B.prototype = {
        param : B
    }
    A.param = 'staticA';
    var a = new A();
    B.call(A); 
    A.show(); //输出staticA
    alert(A.newParam); //输出newB
    alert(A.staticParam); //输出undefined
上述例子中我们可以看到B.call(A),此时因为A相当于类,所以将B中的对象方法变量复制到了类A中,成为了A的类变量方法,而alert(A.staticParam)输出undefined说明B的类变量不会复制到A中。

 

下面我们看第五个实例:

 

function A(){    
       this.param = 'newA';
    }
    function B(){
    	this.newParam = 'newB';
        this.show = function(){
            alert(this.param);
        }
    }
    B.staticParam = 'staticB'; 
    B.prototype = {
        param : B
    }
    A.param = 'staticA';
    var a = new A();
    b.call(A); 

上述例子报Uncaught TypeError: b.call is not a function,可推测call()方法是类方法,实例对象无法调用,而apply()也是类方法,读者可自己测之。

 

好了,现在咱们来总结一下,JS中的call()和apply()方法是函数对象的类方法,方法的第一个参数表示当前需转换的域对象,可以为对象实例,也可以为类。而只有函数的对象变量方法才能复制到新的执行域中,当执行域为类对象,则需用类对象来引用,否则需用实例对象引用。笔者在本篇文章中都是用的call()函数来举例,apply()其实和call()用法基本一样,后面笔者将会写一篇专门比较apply()和call()的文章。

 

Tags:

相关文章

    文章评论

    最 近 更 新
    热 点 排 行
    Js与CSS工具
    代码转换工具
    
    <