`

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、bind的用法之旅模式

    为了控制函数的this指向,JavaScript提供了apply、call以及bind方法。以下详细解释了apply、call以及bind的用法,并通过实例加深理解。 1. apply()和call()方法 apply()和call()方法都用于指定函数体内this的值。...

    JavaScript中的apply和call函数详解_.docx

    在JavaScript中,`apply`和`call`是两种非常重要的函数调用方式,它们都用于改变函数内部`this`的指向以及动态传递参数。这两者的主要区别在于参数的传递方式。 首先,`this`在JavaScript中是一个关键字,它在不同...

    关于Javascript中call与apply的进一步探讨

    在JavaScript中,`call`和`apply`是两个非常重要的方法,它们都用于改变函数调用时的上下文(即`this`的值),并且可以灵活地传递参数。本篇文章将深入探讨这两个方法的用法、区别以及实际应用场景。 `call`方法...

    理解JavaScript的caller callee call apply

    `call`和`apply`是`Function.prototype`上的两个方法,它们允许开发者以不同的上下文(`this`值)调用函数,并提供参数。这两个方法的主要区别在于参数的传递方式: 1. **`call`方法**:接收一个`this`值作为第一个...

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

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

    javascript中apply、call和bind的用法区分_.docx

    ### JavaScript中apply、call和bind的用法区分 在JavaScript编程中,`apply`、`call`和`bind`这三个方法被广泛用于改变函数内部`this`的指向,这对于理解和编写复杂的JavaScript代码至关重要。虽然它们的功能相似,...

    javascript技术难点(三)之this、new、apply和call详解

    JavaScript中的this、new、apply和call是理解JavaScript面向对象编程的关键知识点。首先,我们要知道,this关键字在JavaScript中表示当前上下文的对象,但它并不像Java中的this那样始终指向同一个对象。JavaScript的...

    浅谈javascript中的call、apply、bind_.docx

    JavaScript 中的 call、apply、bind 方法是 Function 对象自带的三个方法,这三个方法的主要作用是转变函数中的 this 指向,从而可以达到“接花移木”的效果。下面将对这三个方法进行具体的讲解,并列出几个经典应用...

    跟我学习javascript的call(),apply(),bind()与回调

    本文将详细解释JavaScript中call(), apply(), 和 bind() 方法的作用、语法以及使用场景,并且会探讨回调函数的使用,帮助理解这些概念在实际编程中的应用。 首先,我们来探讨call() 和 apply() 方法。这两个方法都...

    Javascript - 全面理解 caller,callee,call,apply (转载)

    这篇文章将深入探讨四个关键概念:caller、callee、call和apply,它们都是JavaScript函数操作的核心部分,对于理解和使用高级JavaScript编程至关重要。 首先,我们来了解`caller`和`callee`。在JavaScript的函数...

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

    总结起来,`call()` 和 `apply()` 都用于立即调用函数并改变 `this` 的值,不同之处在于传递额外参数的方式:`call()` 是按位置传递,`apply()` 是通过数组传递。而 `bind()` 不仅可以改变 `this` 的值,还可以返回...

    js中apply与call简单用法详解.docx

    在JavaScript中,`apply`与`call`是两个非常重要的函数,它们都属于`Function.prototype`的一部分,因此每一个函数对象都拥有这两个方法。这两个方法的主要作用在于改变函数执行时的上下文环境(`this`值),这对于...

    javascript中call和apply方法浅谈

    在JavaScript中,`call`和`apply`是两种非常重要的函数调用方式,它们都用于改变函数内部`this`的指向,实现函数的动态绑定。这两个方法都是Function对象的原型方法,可以应用到任何函数上。 首先,让我们深入理解`...

    js中call与apply的用法小结

    在JavaScript中,`call` 和 `apply` 是两种非常重要的函数调用方式,它们都用于改变函数执行时的上下文,即`this`的指向。本文将深入探讨这两种方法的用法及其在实际编程中的应用。 ### 1. `call` 的基本用法 `...

    深化理解关于javascript中apply()和call()方法的区分_.docx

    在JavaScript中,`apply()`和`call()`方法都是用于改变函数调用时的上下文(即`this`关键字指向的对象)以及传递参数。这两个方法都隶属于`Function.prototype`,因此所有函数实例都拥有这两个方法。它们的主要作用...

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

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

    javascript中apply/call和bind的使用

    总结来说,apply()、call()和bind()在JavaScript中都是非常重要的方法,它们可以控制函数内部的this指向,允许参数的灵活传递,并且可以创建可重用的函数,从而提升代码的模块性和灵活性。通过理解这些方法的使用...

    Javascript 中的 call 和 apply使用介绍

    JavaScript中的`call`和`apply`是两种非常重要的函数调用方式,它们允许开发者改变函数执行的上下文,即函数内部的`this`值。这两个方法的主要区别在于传递参数的方式。 `call`方法的语法是`call(obj, arg1, arg2, ...

    JavaScript中的apply和call函数详解

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

Global site tag (gtag.js) - Google Analytics