`

javascript之function的apply(), call()

阅读更多
接上文:
javascript之function的this   

____________________________________________________________________


一、关于apply 和 call 是什么

Function.prototype.apply():

- The apply() method calls a function with a given this value and arguments provided as an array.
- 指定函数执行时的上下文对象 this,和执行参数,并执行函数。


call() 方法与 apply() 方法相同,不同的只是参数的格式。



二、用例剖析

考虑以下这段代码:
<input type="button" id="btnSubmit" value="Click me!" />

<script language="javascript" type="text/javascript">

    function ButtonMessager(buttonId, msg){
       
       this.message = msg;
       
       //在面向对象编程的函数体内,可以有面向过程的语句。
       document.getElementById(buttonId).onclick = this.showMessage;  
  
    }
    
    ButtonMessager.prototype.showMessage=function(){        
        alert(this.message);
    }
    
   var btnMessager = new ButtonMessager("btnSubmit", "Hello!");
   
</script>


    按预想的意图,当点击按钮时,应当会弹出 "Hello!",但上面的代码运行,却弹出 "undefined" 。问题出在哪里呢?在12行设个断点,对它进行调试,发现 this 竟然是指向 btnSubmit,如果是这样的话,那就难怪会弹出 "undefined",因为 btnSubmit 本身并没有定义 message

    事实上,这是与Javascript的语法和运行机制有关的,当 showMessage 真正调用前,this 的指向是不明确,而只有在运行里,this 的指向会由运行时来决定。


    那么有没有什么方法来正确实现上述意图呢?答案是肯定的。

    首先看下面的代码:
var x=10;
var o ={ x: 15 };
function foo(){
    alert(this.x);
}

foo();         // 10
foo.call(o);   // 15


    function.call()方法的意义在于,当调用它时,函数使用给定的this作为上下文对象运行。
    当调用 foo() 时,this是指向window的(所有的全局变量就是window的属性)。
    当调用 foo.call(o) 时,this指向给定的 o 。


    理解了function.call的作用,当解决上面的问题就不难了:
<input type="button" id="btnSubmit" value="Click me!" />

<script language="javascript" type="text/javascript">
    function ButtonMessager(buttonId, msg){
        this.message = msg;
        
        // 当 click 事件触发时,this 不再指向 btnSubmit
        // 而是指定的 ButtonMessager 生成的 对象:btn
        document.getElementById(buttonId).onclick = createDelegate(this,this.showMessage);
    }
    
    ButtonMessager.prototype.showMessage=function(){        
        alert(this.message);
    }
    
    function createDelegate(object, method){
        return function(){
            method.apply(object);
        }    
    }
    
    var btn = new ButtonMessager("btnSubmit", "Hello!");        

</script>
</script>




四、apply() 与 call() 辩析

What is the difference between using call and apply to invoke a function?[1]
var func = function(){
    alert('hello!');
};

func.apply();
//vs
func.call();


Are there performance differences between the two methods? When is it best to use call over apply and vice versa?


Anwser:

The difference is that:
    - apply lets you invoke the function with arguments as an array;
    - call requires the parameters be listed explicitly.

A useful mnemonic is "A for array and C for comma."

See MDN's documentation on apply and call.

Pseudo syntax:
//
     theFunction.apply(valOfThis, arrayOfArgs)
//
//
     theFunction.call(valOfThis, arg1, arg2, ...)
//


Sample code:

function theFunction(name, profession) {
    console.log("My name is " + name + " and I am a " + profession + ".");
}
theFunction("John", "fireman");
theFunction.apply(undefined, ["Susan", "school teacher"]);
theFunction.call(undefined, "Claude", "mathematician");

// My name is John and I am a fireman.
// My name is Susan and I am a school teacher.
// My name is Claude and I am a mathematician.




五、补充说明:

相同点:
        都是指定函数运行时的上下文对象:this, 并执行函数。
不同点:
        apply 可以将参数作为数组的形式传递
        call 传递参数,必须一个个明确列出来

fun.apply(thisArg[, argsArray])
Calls a function with a given this value and arguments provided as an array (or an array like object).
Description:
You can assign a different this object when calling an existing function. this refers to the current object, the calling object.
apply is very similar to call, except for the type of arguments it supports.[2]

fun.call(thisArg[, arg1[, arg2[, ...]]])
Calls a function with a given this value and arguments provided individually.
Description:
You can assign a different this object when calling an existing function. this refers to the current object, the calling object.[3]


六、参数个数过长的处理

例子(可以直接运行):
function minOfArray(arr) {
    var min = Infinity;
    var QUANTUM = 32768;

    for (var i = 0, len = arr.length; i < len; i += QUANTUM) {
        var submin = Math.min.apply(null, arr.slice(i, Math.min(i + QUANTUM, len)));
        min = Math.min(submin, min);
    }

    return min;
}

var min = minOfArray([5, 6, 2, 3, 7]);

alert(min);


说明:
But beware: in using apply this way, you run the risk of exceeding the JavaScript engine's argument length limit. The consequences of applying a function with too many arguments (think more than tens of thousands of arguments) vary across engines (JavaScriptCore has hard-coded argument limit of 65536), because the limit (indeed even the nature of any excessively-large-stack behavior) is unspecified. Some engines will throw an exception. More perniciously, others will arbitrarily limit the number of arguments actually passed to the applied function. (To illustrate this latter case: if such an engine had a limit of four arguments [actual limits are of course significantly higher], it would be as if the arguments 5, 6, 2, 3 had been passed to apply in the examples above, rather than the full array.) If your value array might grow into the tens of thousands, use a hybrid strategy: apply your function to chunks of the array at a time:[4]


七、用法之一: 对匿名函数使用 call() 方法

var animals = [
  {species: 'Lion', name: 'King'},
  {species: 'Whale', name: 'Fail'}
];

for (var i = 0; i < animals.length; i++) {
  (function (i) { 
    this.print = function () { //add print method for arguments.
      console.log('#' + i  + ' ' + this.species + ': ' + this.name); 
    } 
    this.print();
  }).call(animals[i], i);
}

In this purely constructed example, we create anonymous function and use call to invoke it on every object in an array. The main purpose of the anonymous function here is to add a print function to every object, which is able to print the right index of the object in the array. Passing the object as this value was not strictly necessary, but is done for explanatory purpose.


八、用法之二: Ext中的模板写法
var fn = function(){
    fn.superclass.constructor.apply(this,arguments);
}

Ext.extend(fn, Ext.util.Observable,{
    
});

superclass 是一个代指(变量),指向fn继承的父类。fn继承了谁,superclass就是谁。
constrctor 是也是变量,代指superclass的构造方法。

fn.superclass.constructor.apply(this,arguments);
指在创建 superclass 时,使用其构造方法,加入 arguments 作为参数,一起创建。


问题:superclass不是javaScript关键字,又怎么可以直接用呢?它是怎么产生的?
解释:
The Ext.extend method create a "superclass" property that point to the prototype of the Superclass, this allow you to execute or read any method or property in the superclass (that is defined in it's prototype).[5]






引用:
[1].http://stackoverflow.com/questions/1986896/what-is-the-difference-between-call-and-apply
[2].[4].https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply
[3].https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/call
[5].http://www.sencha.com/forum/showthread.php?128276-Extend-how-to-call-parent-s-superclass




—————————————

javascript 函数基础系列文章

1、JavaScript之变量的作用域
2、javascript之变量类型与变量声明及函数变量的运行机制
3、javaScript之function定义
4、javascript之function的prototype对象
5、javascript之function的(closure)闭包特性
6、javascript之function的this   
7、javascript之function的apply(), call()



___________


javascript 面向对象编程系列文章:

    1、javaScript之面向对象编程
    2、javascript之面向对象编程之属性继承
    3、javascript之面向对象编程之原型继承 
   

-



-
转载请注明
原文出处: http://lixh1986.iteye.com/blog/1943409





-
2016-07-12
-



分享到:
评论

相关推荐

    JavaScript中函数(Function)的apply与call理解

    主要介绍了JavaScript中函数(Function)的apply与call理解,本文讲解了JavaScript函数调用分为4中模式以及通过apply和call实现扩展和继承两方面,需要的朋友可以参考下

    javascript中apply和call方法的作用及区别说明

    1、call,apply都属于Function.prototype的一个方法,它是JavaScript引擎内在实现的,因为属于Function.prototype,所以每个Function对象实例(就是每个方法)都有call,apply属性。既然作为方法的属性,那它们的使用...

    开启Javascript中apply、call、bind的用法之旅模式

    在Javascript中,Function是一种对象。Function对象中的this指向决定于函数被调用的方式,使用apply,call 与 bind 均可以改变函数对象中this的指向。

    JavaScript中apply与call的用法意义及区别说明

    apply和call,它们的作用都是将函数绑定到另外一个对象上去运行,两者仅在定义参数的方式有所区别: Function.prototype.apply(thisArg,argArray); Function.prototype.call(thisArg[,arg1[,arg2…]]); 从函数原型...

    JavaScript中的apply和call函数详解

    Function.apply and Function.call in JavaScript 第一段略。 每个JavaScript函数都会有很多附属的(attached)方法,包括toString()、call()以及apply()。听起来,你是否会感到奇怪,一个函数可能会有属于它自己的...

    javascript中call apply 的应用场景

    call, apply都属于Function.prototype的一个方法,它是JavaScript引擎内在实现的,因为属于Function.prototype,所以每个Function对象实例,也就是每个方法都有call, apply属性.

    全面解析JavaScript中apply和call以及bind(推荐)

    在谈论JavaScript中apply、call和bind这三兄弟之前,我想先说下,函数的调用方式有哪些: •作为函数 •作为方法 •作为构造函数 •通过它们的call()和apply()方法间接调用 前面的三种调用方法,我们都知道且不...

    Javascript中apply、call、bind的巧妙使用

    在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向。 JavaScript 的一大特点是,函数存在「定义时上下文」和「运行时上下文...

    javascript中apply、call和bind的使用区别

    在说区别之前还是先总结一下三者的相似之处: 1、都是用来改变函数的this对象的指向的。 2、第一个参数都是this要指向的对象。 3、都可以利用后续参数传参。 那么他们的区别在哪里的,先看一个例子。 var xw = { ...

    Javascript 中的 call 和 apply使用介绍

    简单的说就是改变函数执行的上下文,... 这两个方法通常被用来类的继承和回调函数: 作用一、类的继承: 先来看这个例子: 代码如下: function Person(name,age){ this.name = name; this.age=age; this.alertName = f

    apply和call方法定义及apply和call方法的区别

    如果没接触过动态语言,以编译型语言的思维方式去理解javaScript将会有种神奇而...call, apply都属于Function.prototype的一个方法,它是JavaScript引擎内在实现的,因为属于Function.prototype,所以每个Function对象实

    JavaScript 中 apply 、call 的详解

    apply 和 call 的区别 ECMAScript 规范给所有函数都定义了 call 与 apply 两个方法,它们的应用非常广泛,它们的作用也是一模一样,只是传参的形式有区别而已。 apply( ) apply 方法传入两个参数:一个是作为函数上...

    javascript中call apply 与 bind方法详解

    在JavaScript中,call、apply和bind是Function对象自带的三个方法,本文将通过几个场景的应用,来详细理解三个方法。 call() call() 方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法。 ...

    javascript中call,apply,bind函数用法示例

    本文实例讲述了javascript中call,apply,bind函数用法。分享给大家供大家参考,具体如下: 一.call函数 a.call(b); 简单的理解:把a对象的方法应用到b对象上(a里如果有this,会指向b) call()的用法:用在函数上面 ...

    Javascript中call,apply,bind方法的详解与总结

    1.call/apply/bind方法的来源 2.Function.prototype.call() 3.Function.prototype.apply()  3.1:找出数组中的最大数  3.2:将数组的空元素变为undefined  3.3:转换类似数组的对象 4.Function.prototype.bind() ...

    彻底搞懂JavaScript中的apply和call方法(必看)

    call和apply都是为了改变某个函数运行的context上下文而存在的,即为了改变函数体内部this的指向。因为JavaScript的函数存在定义上下文和运行时上下文以及上下文是可以改变的概念。 回到目录定义 fun.apply(thisArg...

    深入理解JavaScript中的call、apply、bind方法的区别

    在JavaScript 中,this的指向是动态变化的,很可能在写程序的过程中,无意中破坏掉this的指向,所以我们需要一种可以把this的含义固定的技术,于是就有了call,apply 和bind这三个方法,来改变函数体内部 this 的...

    简单对比分析JavaScript中的apply,call与this的使用

    简单的说call,apply都属于Function.prototype的一个方法,它是JavaScript引擎内在实现的,因为属于Function.prototype,所以每个Function对象实例(就是每个方法)都有call,apply属性。既然作为方法的属性,那它们的...

    javascript call和apply方法

    例子如下: 代码如下:[removed] /** *动物 */ function Animal(){ this.name=’Amimal’;...//创建猫对象 animal.showName.call(cat,”,”);//输出cat,说明showName函数的当前this已经变为cat了 animal.showName

Global site tag (gtag.js) - Google Analytics