te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>Can you create functions with custom prototypes in JavaScript? - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Can you create functions with custom prototypes in JavaScript? - Stack Overflow

programmeradmin4浏览0评论

First of all, I don't want to add methods to Function.prototype. Doing that would make them available for all functions and that's not what I'm looking for.

In JavaScript you can create objects with custom prototypes like this:

function CustomObj() {}
CustomObj.prototype = {};
CustomObj.prototype.sayFoo = function () { return 'foo' };

var myCustomObj = new CustomObj(); //=> returns an object: {}
myCusomObj.sayFoo(); //=> 'foo'

You can also create array-like objects with custom prototypes like this:

function CustomArr() {}
CustomArr.prototype = [];
CustomObj.prototype.sayFoo = function () { return 'foo' };

var myCustomArr = new CustomArr(); //=> returns an ordered object: []
myCustomArr.sayFoo(); //=> 'foo'

What I'd like to do is use some kind of constructor to create a function with its own custom prototype in the same way. However, the following does not work:

function CustomFn() {}
CustomFn.prototype = function () {};
CustomFn.prototype.sayFoo = function () { return 'foo' };

var myCustomFn = new CustomFn(); //=> PROBLEM! returns an object: {}
myCustomFn.sayFoo(); //=> 'foo'

// ^^ Here, the prototype was applied but the output was not a function.
myCustomFn(); //=> TypeError: object is not a function

So is there any way to acplish what I'm trying to do?

UPDATE

Maybe there's another way I could be asking this question that would make it a little clearer.

There's a problem with the idea of a closure:

function makeFn() {
  var output = function () { /* do some stuff */ };
  output.foo = function () { /* do some stuff */ };
  return output;
}
var specialFn = makeFn();

Essentially, this technique gives me what I want. However, the problem is that every time I call makeFn, output.foo has to be created as a totally independent function that takes up its own memory. Gross. So I could move that method out of the closure:

var protoMethods = {
  "foo" : function () { /* do some stuff */ }
};
function makeFn() {
  var output = function () { /* do some stuff */ };
  for (var i in protoMethods) {
    Object.prototype.hasOwnProperty.call(protoMethods, i) &&
      (output[i] = protoMethods[i]);
  }
  return output;
}
var specialFn = makeFn();

But now I have to manually do an iteration every time I call makeFn which would be less efficient than if I could just assign protoMethods to be the prototype of output. So, with this new update, any ideas?

First of all, I don't want to add methods to Function.prototype. Doing that would make them available for all functions and that's not what I'm looking for.

In JavaScript you can create objects with custom prototypes like this:

function CustomObj() {}
CustomObj.prototype = {};
CustomObj.prototype.sayFoo = function () { return 'foo' };

var myCustomObj = new CustomObj(); //=> returns an object: {}
myCusomObj.sayFoo(); //=> 'foo'

You can also create array-like objects with custom prototypes like this:

function CustomArr() {}
CustomArr.prototype = [];
CustomObj.prototype.sayFoo = function () { return 'foo' };

var myCustomArr = new CustomArr(); //=> returns an ordered object: []
myCustomArr.sayFoo(); //=> 'foo'

What I'd like to do is use some kind of constructor to create a function with its own custom prototype in the same way. However, the following does not work:

function CustomFn() {}
CustomFn.prototype = function () {};
CustomFn.prototype.sayFoo = function () { return 'foo' };

var myCustomFn = new CustomFn(); //=> PROBLEM! returns an object: {}
myCustomFn.sayFoo(); //=> 'foo'

// ^^ Here, the prototype was applied but the output was not a function.
myCustomFn(); //=> TypeError: object is not a function

So is there any way to acplish what I'm trying to do?

UPDATE

Maybe there's another way I could be asking this question that would make it a little clearer.

There's a problem with the idea of a closure:

function makeFn() {
  var output = function () { /* do some stuff */ };
  output.foo = function () { /* do some stuff */ };
  return output;
}
var specialFn = makeFn();

Essentially, this technique gives me what I want. However, the problem is that every time I call makeFn, output.foo has to be created as a totally independent function that takes up its own memory. Gross. So I could move that method out of the closure:

var protoMethods = {
  "foo" : function () { /* do some stuff */ }
};
function makeFn() {
  var output = function () { /* do some stuff */ };
  for (var i in protoMethods) {
    Object.prototype.hasOwnProperty.call(protoMethods, i) &&
      (output[i] = protoMethods[i]);
  }
  return output;
}
var specialFn = makeFn();

But now I have to manually do an iteration every time I call makeFn which would be less efficient than if I could just assign protoMethods to be the prototype of output. So, with this new update, any ideas?

Share Improve this question edited May 16, 2013 at 20:34 Stupid Stupid asked May 16, 2013 at 19:44 Stupid StupidStupid Stupid 2151 gold badge4 silver badges9 bronze badges 2
  • I tried that too, when working on V library. So no, using the new operator, you can only create new "object"s, but not new "function object"s. However you can use a constructor function both as a constructor and as a function! – metadings Commented May 16, 2013 at 19:49
  • 2 That's disappointing. There would be so many really interesting and creative applications of this kind of technique if we had it. Seems like it should go hand in hand with the concept of a closure. Sure, I can return a function with methods attached, but that means every time I invoke the closure I'm doing a less-optimized iteration, and creating totally new functions every time. – Stupid Stupid Commented May 16, 2013 at 19:57
Add a ment  | 

3 Answers 3

Reset to default 5

It is a tricky thing indeed, more plicated than it should be if the language was designed well...

Basically, you just can't do it cleanly in current versions. Objects other than functions can not be callable.

In future Javascript versions, you can do it with a "proxy" object that can define a "call" handler. But it is still way too plicated and contrived in my opinion.

Another way to go about it is to make your object a real function, not a custom object. Then try to set its __proto__, which is non-standard yet but works in most modern browsers, except Opera and IE 8 or less. Also maybe set its constructor property for faking instanceof checks... such hacks are quite tricky though and results will vary a lot with environments.

The following example works fine on my Firefox: http://jsfiddle/Q3422/2/

function MyFun() {
    if (!this || this==window) {
        return new MyFun();
    }

    var f = function() {
        return "thanks for calling!";
    }
    f.__proto__ = MyFun.prototype;
    f.constructor = MyFun;

    return f;
}

MyFun.prototype = {
    foo: function() {
        return "foo:" + this();
    },
    __proto__: Function.prototype
};

var f = new MyFun();
alert("proto method:"+f.foo()); // try our prototype methods
alert("function method:"+f.call()); // try standard function methods
alert("function call:"+f()); // try use as a function
alert('typeof:' + typeof f); // "function", not "object". No way around it in current js versions
alert('is MyFun:' + (f instanceof MyFun)); // true
alert('is Function:' + (f instanceof Function)); // true

Just wanted to add that you should not be worried about "copying" functions to each instance of your objects. The function itself is an object, so is never really copied, nor is it repiled or anything. It does not waste memory, except for the function object reference itself and any closure variables.

Iterating over the prototype to copy it should not concern you as well, I guess you will not have a gazillion methods.

So your own last solution is probably the best if you need to support environments where proto is not settable, and you are not worried that your prototype might get extended after some objects already got created and they may not pick up the changes.

You're at the heart of what inheritance in JavaScript is all about. Yes, since prototypes are objects, you'll want to set the prototype of CustomFn to an object instead of a function.

But that object can e from another function:

function ParentFn() {}
function CustomFn() {}
CustomFn.prototype = Object.create(ParentFn.prototype);
CustomFn.prototype.sayFoo = fun ...

If you don't have ES5 or a polyfill:

CustomFn.prototype = (function() {
                          function F(){}
                          F.prototype = ParentFn.prototype;
                          return new F();
                      }());

Some may tell you just to do the following but the above way is better:

CustomFn.prototype = new ParentFn();

I tried that too, when working on V library. I wanted to override the Function constructor to enforce a restricted syntax of constructor functions, that I'm calling "class functions" (and I'm confident to do so).

Answer is no, using the new operator you can only create new "object"s, but not new "function object"s.

However you can use a constructor function both as a constructor and as a function!

var CustomFn = function () {
  if (this instanceof CustomFn) {
    // here we are 'new CustomFn()'
  }
  else {
    // here we are 'CustomFn()' or 'CustomFn.call()'
  }
};

Or as I believe is the better concept, to do the function in first place and then let the constructor go:

var CustomFn = function () {
  if (!(this instanceof CustomFn)) { // functioning
    // here we are 'CustomFn()' or 'CustomFn.call()'
    return new CustomFn(); // or return undefined or throw
  }

  // constructing
  // here we are 'new CustomFn()'

  // BaseCustomFn.call(this);
};
发布评论

评论列表(0)

  1. 暂无评论