7

我实际上正在研究 Crockford 的Javascript: the good parts。我是 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

4

3 回答 3

5

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

F.method(a).method(b).method(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|
于 2011-02-11T20:37:55.787 回答
5

让我试着解释一下。我没有读过那本书,但是 Douglas Crockford 的一篇文章Classical Inheritance in JavaScript有一个重要的句子,与关于 Function.prototype.method 的示例相关:

它返回这个。当我编写一个不需要返回值的方法时,我通常让它返回 this。它允许级联式编程。

实际上我不熟悉这个术语,我认为众所周知的术语是“ Fluent Interface ”或“Method Chaining”,阅读那个wiki页面,有不同语言的示例,所以你会理解它..

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:通常我在处理实体(例如 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 - 对我来说简短且足以看到利弊(以及其他资源的链接)

于 2011-02-11T20:38:42.980 回答
0

我不明白你问什么,但如果你不返回任何东西,你将不会为 Function.prototype.method 分配任何东西,女巫会让这句话毫无用处,你不觉得吗?

于 2011-02-11T10:26:59.870 回答