JavaScript扩展类型返回

时间:2011-02-11 09:57:59

标签: javascript extension-methods prototypal-inheritance function-prototypes

我实际上在研究Crockford的 Javascript:好的部分。我是JavaScript的新手,所以我很难理解这段代码的工作原理:

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};

以下是我的想法:

作为一个方法(对象内部的一个函数),this指向Function对象,但为什么需要返回该对象,因为我从方法内部访问它?如果我是对的,this是参考,而不是本地副本,所以:

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
};

应该也可以。

另一方面,在JavaScript中,没有return语句的函数返回undefined并将其分配给Function.prototype.method

问题

返回this有什么意义?


工作示例#1

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};
var add = function(a, b) {
    return a+b;
};

Function.method('add', add);
var f = function() {};

print(f.add(1,2));

Number.method('integer', function () {
        return Math[this < 0 ? 'ceil' : 'floor'](this);
        });

print((-10/3).integer());

输出:

  

-3   3


工作示例#2

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
};

var add = function(a, b) {
    return a+b;
};

Function.method('add', add);
var f = function() {};

print(f.add(1,2));

Number.method('integer', function () {
        return Math[this < 0 ? 'ceil' : 'floor'](this);
        });

print((-10/3).integer());

输出:

  

-3    3

3 个答案:

答案 0 :(得分:5)

今天下午我已经发送了一封电子邮件给Douglas Crockford这个问题,他的答复是:

  

F.method的(a)。方法(b)中。方法(c)中

我不是在开玩笑。这是他写的唯一的事情。

无论如何,我个人对他(隐秘)答案的解释是创建链方法

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this; //This returns the same Function object into the chain below
};

var add = function (a, b) { return a+b; };
var sub = function (a, b) { return a-b; };
var mul = function (a, b) { return a*b; };
var div = function (a, b) { return a/b; };

Function.method('add', add).method('sub', sub).method('mul', mul).method('div', div);

也就是说,不是一次使用一个行创建新方法,而是可以重新应用链中的下一个方法之前,Function

在此示例中,链从从左到右

|Function|--method-->|add|--returns-->|Function|--method-->|sub|--returns-->|Function|--method-->|mul|--returns-->|Function|--method-->|div|-->returns-->|Function|

答案 1 :(得分:5)

让我试着解释一下。我没有看过那本书,但道格拉斯·克罗克福德的一篇文章Classical Inheritance in JavaScript有一个重要的句子,与关于Function.prototype.method的那个例子有关:

  

它返回此。当我写一个方法   我不需要返回一个值   通常让它归还。它允许   对于级联式的编程。

实际上我对这个术语并不熟悉,我认为众所周知的术语是“Fluent Interface”或“方法链”,阅读维基页面,有不同语言的例子,所以你会理解它。

PS。 @Gianluca Bargelli以这种方式提供使用Function.prototype.method的例子有点快,所以我不在我的回答中发布

ADDON:如何根据您的示例使用它:

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
}

Number.method('integer', function () {  // you add 'integer' method
        return Math[this < 0 ? 'ceil' : 'floor'](this);
        })
      .method('square', function () {  // you add 'square' method with help of chaining
        return this * this;
        });

console.info( (-10/3).integer().square() ); // <- again chaining in action

你看,integer()返回Number对象,所以你可以调用另一个方法,而不是写:

var a = (-10/3).integer();
console.info( a.square() ); 

关于我使用它的方式几句话,大多数时候我更喜欢写“每个方法 - 带缩进的新行,对我来说这种方式更具可读性:

Function.method('add', add)
        .method('sub', sub)
        .method('mul', mul)
        .method('div', div);

通过这种方式,我看到了我的起点,“新行/缩进”告诉我,我仍然会修改该对象。将它与长线比较:

Function.method('add', add).method('sub', sub).method('mul', mul).method('div', div);

或典型方法:

Function.method('add', add);
Function.method('sub', sub);
Function.method('mul', mul);
Function.method('div', div);

ADDON2:我在处理实体时通常使用这种方法(Fluent界面模式),例如Java代码:

public class Person {
  private String name;
  private int age;
  ..

  public String getName() {
    return this.name;
  }

  public Person setName( String newName ) {
    this.name = newName;
    return this;
  }

  public int getAge() {
    return this.age;
  }

  public Person setAge( int newAge ) {
    this.age = newAge;
    return this;
  }

  ..
}

它允许我以简单的方式构造Person对象:

Person person = new Person().setName("Leo").setAge(20);

有些人对它有所不同,他们为set / get添加了新方法,并称之为with

public class Person {
  private String name;
  private int age;
  ..

  public String getName() {
    return this.name;
  }

  public void setName( String newName ) {
    this.name = newName;
  }

  public Person withName( String newName ) {
    this.setName( newName ); // or this.name = newName; up to you
    return this;
  }

  public int getAge() {
    return this.age;
  }

  public void setAge( int newAge ) {
    this.age = newAge;
  }

  public Person withAge( int newAge ) {
    this.setAge( newAge ); // or this.age = newAge; up to you
    return this;
  }
  ..
}

现在我的上一个示例如下:

Person person = new Person().withName("Leo").withAge(20);

这样我们就不会改变set方法的含义(我的意思是我们不会增强它,所以它可以像大多数开发人员所期望的那样工作......至少人们不希望set方法可以返回什么;))。关于这些特殊方法的一个有趣的事情 - 它们可以放松自我记录,但是当你使用它们时它们会提高可读性(例如Person创建的例子,withName非常清楚我们究竟在做什么。

阅读更多:
FluentInterface - Martin Fowler对该模式的描述 Fluent Interfaces in PHP
The Weekly Source Code 14 - Fluent Interface Edition - 至于我的简短和足够好,可以看到利弊(以及其他资源的链接)

答案 2 :(得分:0)

我不明白你的要求,但是如果你没有返回任何东西,你将不会给Function.prototype.method分配任何东西,那么你觉得这句话没用了吗?