自定义的构造函数可以创建函数吗◔ ‸◔?

我们都知道JavaScript中构造函数是用来创建对象实例的。我想知道自定义的构造函数是否可以创建函数实例?或者其他数据类型的实例?

-----------------------2017年1月8日更新-----------------------

根据回答的朋友提示,以闭包的形式创建函数实例,我做了一个演示例子:

function Foo () {
  return function() {
    console.log('Foo');
  }
}

Foo.prototype.outStr = function() {
  console.log('abc');
}

var f = new Foo();
f();
f.outStr();

如果f是Foo构造函数创建的实例,那么实例应该会继承构造函数的prototype原型对象上的属性和方法。
但是上面这段代码中,f.outStr()执行后,会提示f.outStr不是一个函数。也就是说f并没有集成到outStr这个方法。

阅读 4k
4 个回答

谢谢邀请!

首先来说,你是希望构造一个函数对象,而它同时又具有你自定义的类方法……这在 ES6 里其实是很容易通过继承实现的

class Foo extends Function { ... }

不过在 ES5 里也有不是很完美的实现方法,比如改变 f__proto__Foo.prototype。不过这样改过之后你会发现 f 不再具有函数对象的一些方法,比如 call()apply()bind() 等。同时 __proto__ 不在标准中,所以不能保证每一个 JS 引擎都实现了。

回过头来说 ES6 的办法——因为 ES6 可以通过很多工具,比如 babel 翻译成 ES5 的,所以 ES6 实现了,ES5 也就能实现 (现在我对这句话表示怀疑——具体请看后面)

ES6 中,FooFunction 继承,所以可以通过 Foo 构造一个函数对象,同时它可以用 Foo 中定义的方法。但问题在于构造这个对象的时候不能使用 function 定义语法,也不能使用函数表达式等,必须直接使用 Function 构造函数。构造函数需要函数体文本为作参数,比如

const f = new Function("console.log(\"Foo\");");

当然函数体很短的时候不是问题,比较长的时候才是麻烦的事情。当然可以用 es6 引入的 模板字符串 来解决,它允许多行字符。这会损失编辑器对其语法的检查。所以我的办法是定义一个临时函数,再通过 toString() 和正则表达式把函数体找出来。

最终完成的代码是这样的:

// es6 syntax

const body = function() {
    console.log("Foo");
}.toString().replace(/^function\s*\(\)\s*\{|\}$/g, "");

class Foo extends Function {
    constructor() {
        super(body);
    }

    outStr() {
        console.log("abc");
    }
}

var f = new Foo();
f();
f.outStr();

不过很遗憾,使用 TypeScript 和 Babel 转出来的 es5 代码都不能运行……

谢邀,典型的this指向没搞清楚。

构造函数中的 this
当一个函数被作为一个构造函数来使用(使用new关键字),它的this与即将被创建的新对象绑定。
注意:当构造器返回的默认值是一个this引用的对象时,可以手动设置返回其他的对象,如果返回值不是一个对象,返回this。

构造函数中的_this

new运算符

当代码 new foo(...) 执行时:
一个新对象被创建。它继承自foo.prototype.
构造函数 foo 被执行。执行的时候,相应的传参会被传入,同时上下文(this)会被指定为这个新实例。new foo 等同于 new foo(), 只能用在不传递任何参数的情况。
如果构造函数返回了一个“对象”,那么这个对象会取代整个new出来的结果。如果构造函数没有返回对象,那么new出来的结果为步骤1创建的对象,ps:一般情况下构造函数不返回任何值,不过用户如果想覆盖这个返回值,可以自己选择返回一个普通对象来覆盖。当然,返回数组也会覆盖,因为数组也是对象。

当然可以呀,函数也是一个对象。

function Func() {
    return function(){
        console.info("hello");
    };
}

new Func()();

更新一下:

楼主同学,JavaScript的语言特性就那样,了解清楚了灵活运用就行,构造函数显式 return 一个对象时,会取代默认的 this,所以不会应用构造函数原型链上的任何属性和方法。

如果你只是想实现你问题里的表现,那可以这样呀:

function Foo () {
  var self = function () {
    console.log('Foo');
  }
  self.outStr = function() {
    console.info('abc');
  }
  return self;
}

var f = new Foo();
f();
f.outStr();

任何函数都可以创建实例,当他创建实例对象时他就被称为构造函数

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题