具有对象属性的函数的新实例化

4

JavaScript中的函数是一等公民 - 但如何与new结合使用?

我知道如何创建一个既像函数又像对象的对象。

fetch.proxy = '127.0.0.1'
fetch(url)

但是我正在尝试想出如何将此与创建一个new实例相结合,以便我可以做类似于以下的操作:

a = new Fetch(host, username) 

a(path1) // fetches username@host/path1

a(path2) // fetches username@host/path2

(只有一个实例的不太有用的示例)

以下方法不起作用,因为应用new会返回一个对象(因此会得到TypeError:object is not a function)。

var Fetch = function(a, b){

    if ( (this instanceof arguments.callee) ){
        //called as constructor
        this.host = a
        this.username = b;
        this.host = 'localhost'

    } else {

   //called as function
   console.log("Fetching "+this.username+'@'+this.host+a);
    }
};

a = new Fetch('host', 'username') 

a('/path1') // TypeError: object is not a function

a('/path2') // TypeError: object is not a function

我一直在研究基于Fetch.prototype.constructor的IT技术,并参考了http://tobyho.com/2010/11/22/javascript-constructors-and/What it the significance of the Javascript constructor property?,但必须承认我开始质疑是否可能实现它。
您有什么好的想法吗?

你愿意接受“工厂”方式而不是“新建”方式吗? - fuyushimoya
1
我认为你在这里有一些非常好的回复信息:https://dev59.com/iXRC5IYBdhLWcg3wP-Zh - fadomire
你可能需要传递两个参数 **(a,b)**,或者可以通过将对象的键值传递来实现,这样参数的数量对你的代码没有影响。 - Himesh Aadeshara
2个回答

2
如何与new结合使用?
这样做没有意义。所有new Foo做的就是创建一个从Foo.prototype继承的新对象。然而,目前不可能让一些函数从除Function.prototype之外的原型继承,因此使用new Something创建函数没有任何优势。
由于你在示例中没有使用prototype,因此无所谓。只需从Fetch返回一个函数即可:
var Fetch = function(host, username){
  function fetch(path) {
     console.log("Fetching " + fetch.username + '@' + fetch.host + path);
  }
  fetch.username = username;
  fetch.host = host;
  return fetch;
};

现在你可以使用或不使用new**来调用Fetch,这并没有区别:
var a = Fetch(host, username);
// same as
var a = new Fetch(host, username);

请注意,在上面的示例中,我将this.username更改为fetch.username。每个函数都有自己的this值,默认情况下不是指向函数实例本身,因此this.username将无法工作。
这将允许在创建后通过a.username = 'something else';等更改主机或用户名。如果您不想要这个功能,只需将fetch.username更改为username即可。
**:如果函数显式返回一个对象,则new将返回该值,而不是从Fetch.prototype继承的新创建的对象。

0
如果您想要某种继承,可以请求您的构造函数创建并返回一个新函数,然后通过setPrototypeOf进行原型化。

const Fetch = function (host, user)
{
  var fetch // new instance of function, relay to model
  
  fetch = function(path) {
    // note we use the closure on instance 'fetch'
    return Fetch.model.apply(fetch, arguments)
  }
  
  // 'setPrototypeOf' is not as borderline as '__proto__',
  // but it has some caveats anyway. Check for example MDN
  // about this.
  Object.setPrototypeOf(fetch, Fetch.model)

  if (host) fetch.host     = host
  if (user) fetch.username = user
  
  return fetch
}

// we name 'model' here; it also works if we 
// say 'prototype' instead.
// It would have been both more meaningful and more confusing at the
// same time, as the prototype would not get used the standard way.
Fetch.model = function (path)
{
  console.log("Fetching " + this.username + '@' + this.host + path)
}
Fetch.model.host     = 'localhost'
Fetch.model.username = 'peter'


var fetch = new Fetch // 'new' is not needed: can say '= Fetch()'
fetch.host = 'paradise'

fetch('/register')
See console output below


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接