如何在Javascript中实现应用模式

时间:2009-12-29 18:12:57

标签: javascript design-patterns

什么是Javascript中的调用模式参考函数调用模式,我该如何使用它? 使用此调用模式有什么好处。

3 个答案:

答案 0 :(得分: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参数({{1 }})。

' world.'call都改变了被调用函数中执行函数(apply关键字)的上下文,但它们之间的差异是使用this,您可以发送一个数组或类似数组的对象作为要执行的函数的参数,这非常有用,例如:

apply

这可以避免一些非常hacky,糟糕(和常见)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

另一个例子,eval('sum(' + args.join() +')'); Math.max方法,这些方法可以接收任意数量的参数,如:

Math.min

但是如果你有一个数字数组呢?

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

另请注意,当var numbers = [2,4,6,8]; numbers.push(10); var max = Math.max.apply(null, numbers); // 10 null用作undefinedthis call参数时,apply对象会引用到全局对象(类似于情况#2,正常函数调用)。

对于this示例,上下文并不真正相关,因为它们就像“static”方法一样,Math.max关键字未在内部使用...

答案 1 :(得分:1)

您还可以使用call / apply进行继承。

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);这将使用Client创建的this实例执行new WebClient。因此,当

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

Client内执行,WebClient实例正在为这些属性分配。

答案 2 :(得分:0)

我不知道任何名为The Apply Pattern的设计模式,所以我并不认为这与设计模式有任何关系。但是,javascript中有一个函数对象的apply方法(以及相应的调用方法),所以我将解释这些。

apply和call方法基本上允许对象从另一个对象“窃取”方法。你会看到,在javascript中,方法很晚才会被绑定:在调用时。仅在调用方法时才解析'this'的值。在正常的方法调用中:

some_object.do_something();

do_something中的'this'关键字指的是some_object。通过应用和通话,您可以重新分配'this'。例如:

some_object.do_something.apply(another_object);

do_something中的'this'关键字现在指的是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);

还有另一个使用案例,这是申请和通话工作方式不同的结果。如果你有一个数组中的所有参数,并且函数需要单独的参数,你可以使用apply来传递数组并让函数看到数组的内容作为单独的参数:

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