2009-12-29 69 views
6

什么是在Javascript应用调用模式参考函数调用模式以及如何使用它适用模式? 使用这种调用模式有什么好处。如何实现在Javascript

回答

24

采用apply是有关功能上下文(this关键字)和参数传递。

首先,我想你应该知道在什么情况下该this关键字隐含集:

1 - 当一个函数被调用的方法(函数被调用为对象的成员):

obj.method(); // 'this' inside method will refer to obj 

2-甲正常的函数调用:

myFunction(); // 'this' inside the function will refer to the Global object 
// or 
(function() {})(); 

-3-当new运算符用于:

var obj = new MyObj(); // this will refer to a newly created object. 

下面是当applycall来,这些方法让你设置明确情况下,当你调用一个函数,例如:

function test(a) { 
    alert(this + a); 
} 

test.call('Hello', ' world!'); 

在上面的代码当test功能称为this关键字设置到字符串('Hello'),以及使所述a参数(' world.')。

两者,callapply变化所调用的函数内的执行功能(this关键字)的上下文中,但它们之间差别是与apply,则可以发送一个数组或数组状物体作为要执行的函数的参数,这是非常有用的,例如:

function sum() { 
    var result = 0; 
    for (var i = 0; i < arguments.length; i++) { 
    result += arguments[i]; 
    } 
    return result; 
} 

var args = [1,2,3]; 
sum.apply(null, args); // will return 6 

这可以避免一些非常哈克,(共同)eval调用,如:

如果您有数字Array

var max = Math.max(2,4,6,8); // 8 

但什么:10

eval('sum(' + args.join() +')'); 

另一个例子中,Math.maxMath.min方法,这些方法可以接收参数一样任意数量?

var numbers = [2,4,6,8]; 
numbers.push(10); 
var max = Math.max.apply(null, numbers); // 10 

还要注意的是,当nullundefined用作this参数与callapply,所述this对象将参照全局对象(类似于情形#2,正常功能调用)。

对于Math.max例如,上下文是不是真的有关,因为它们就像“静态”方法,该this关键词未在内部使用...

+3

+1非常好! ---- – 2009-12-29 18:27:00

+0

啊我想我现在明白了。我错过的全部观点是“这是作为第一个参数提供的价值”。现在,为什么我们想将应用方法区分为单独的调用类型,这是有道理的。 那么什么是差异。通话和应用关键字之间呢? – Priyank 2009-12-29 18:30:41

+0

@cms +1完美打印! – 2011-12-11 16:11:37

0

我不知道任何设计名为“应用模式”的模式,所以我并不认为这与设计模式完全相关。然而,在JavaScript中有一个函数对象的应用方法(以及相应的调用方法),所以我将解释这些方法。

apply和call方法基本上允许一个对象从另一个对象中“窃取”一个方法。你会发现,在JavaScript中,方法非常迟到:在调用时。只有在调用方法时,才能解决'this'的值。在通常的方法调用:

some_object.do_something(); 

在do_something的'this'关键字引用some_object。申请并致电,让您重新分配'this'。例如:

some_object.do_something.apply(another_object); 

'this' do_something now中的关键字指的是another_object。所以你在another_object上调用属于some_object的do_something方法。

现在,这是有趣的,但为什么会有人想这样做?这就是为什么这是非常有用的一个具体的例子:

// say you want to get some DIVs in the document, you can get all of them with: 
var some_divs = document.getElementsByTagName('DIV'); 

// say you want the third to fifth DIV in the document, some_divs looks like an 
// array so you might think you can slice it, but it's not. It's a collection 
// of elements that fakes being an array and doesn't implement the slice method. 

// No worries, we can steal the slice method from an array 
// and apply it to some_divs: 
var wanted_divs = [].slice.apply(some_divs,[2,5]); 

// Alternatively: 
var wanted_divs = [].slice.call(some_divs,2,5); 

还有另一种使用情况适用的是之间如何应用和呼叫作品差异的结果。如果你把所有的参数在数组和函数需要单个参数,您可以使用适用于传递数组和具备的功能看不到阵列作为单独的参数的内容:

function some_function (first,second) { 
    alert(first+second); 
} 
var argument_array = ['hello','world']; 
some_function.apply(null, argument_array); 
1

您还可以使用呼叫/申请继承。

function Client (id) { 
    this.id = id; 
    this.name = "Client" + id; 
} 

Client.prototype = { 
    constructor: Client 

    , toString: function() { 
     return this.name; 
    } 
}; 

function WebClient (id) { 
    Client.call (this, id); 
} 

WebClient.prototype = new Client(); 

WebClient.prototype.constructor = WebClient; 

WebClient.prototype.ping = function() { 
    // do stuff 
}; 

通知Client.call (this, id);此使用this实例,一个new WebClient会造成执行Client。因此,当

this.id = id; 
    this.name = "Client" + id; 

在内部Client执行WebClient实例得到分配的那些属性。