在JavaScript中查找构造函数名称

时间:2014-06-05 11:43:50

标签: javascript

我需要在JavaScript中实现两个函数:isConstructor(x)constructorName(x)

如果参数isConstructor(x)是构造函数,则

true应返回x,否则返回false。例如,

isConstructor(Date)      ===  true
isConstructor(Math.cos)  ===  false

constructorName(x)应返回每个正确的构造函数x的构造函数名称。例如,

constructorName(Date)  ===  'Date'

我只能想到两个函数的丑陋实现,我创建了一个command字符串   “var y = new x()” 然后在eval(command)语句中使用try/catch调用它。如果eval调用成功,我将x称为构造函数。我通过询问x原型的类名来间接检索y的名称,类似

var constrName = Object.prototype.toString.call(y).slice(8,-1); // extracts the `ConstrName` from `[object ConstrName]`
return constrName;

但当然,这一切都非常难看。 我该怎么做呢?

5 个答案:

答案 0 :(得分:2)

许多人在JavaScript中说过,几乎所有函数对象都是构造函数(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function)。但是,如果要区分不能构造函数的本机函数,可以尝试:

function isConstructor(x) {
    return typeof x === 'function' && typeof x.prototype !== 'undefined';
}

获取名称绝对比较棘手,您可以使用Function.prototype.toString.apply(x)并匹配名称,但例如使用jQuery对象作为空字符串,即如果它是匿名函数。

答案 1 :(得分:1)

这个假设的问题只有一个近似值;是否可以使用new调用函数无法在不实际尝试执行此类调用并检查TypeError的情况下可靠地完成:

function isConstructor(fn)
{
    try {
        var r = new fn(); // attempt instantiation
    } catch (e) {
        if (e instanceof TypeError) {
            return false; // probably shouldn't be called as constructor
        }
        throw e; // something else went wrong
    }
    return true; // some constructors may not return an instance of itself
}

这个问题:

  1. 除了不应该将其作为构造函数调用之外,任何函数都可以选择抛出TypeError;
  2. 构造函数可能需要传递某些参数;
  3. 构造函数的返回值不必满足instanceof obj === func;
  4. 的要求
  5. 通话本身会产生副作用。

答案 2 :(得分:1)

构造函数的定义是一个实现内部[[Construct]]方法的Object。测试它的唯一方法是将其称为构造函数,看看会发生什么。您无法使用[[Class]]来测试Object.prototype.toString属性以外的内部属性。

默认情况下,任何用户定义的ECMAScript函数都是构造函数,例如

function foo(){}

可以作为构造函数调用。函数是实现内部[[Call]]方法的对象,因此 typeof 将返回“function”。但并非所有函数都是构造函数,例如

typeof document.getElementById  // function

new document.getElementById()

会抛出一个类型错误,因为它不是构造函数。还有一些不是函数的构造函数:

typeof XMLHttpRequest  // object

XMLHttpRequest 是一个构造函数,但它没有[[Call]]因此无法作为函数调用:

var x = XMLHttpRequest() // TypeError: XMLHttpRequest isn't a function

最后,您可以尝试测试作为对象或函数的 prototype 属性,但这也不可靠,因为 prototype 属性可以添加到漂亮任何对象,主人或本地人。

所以底线是try..catch可能是唯一的方法。

答案 3 :(得分:0)

如果您不介意创建该功能的测试实例,可以执行以下操作:

function isConstructor(func) {
    var t = new func();
    return (t instanceof func);
}

但是:只有在构造函数不接受任何参数时才会起作用。它也可能抛出异常。如果是这样,你可以尝试其他(不太可靠)的东西,比如检查函数的名称是否以大写字母开头。

答案 4 :(得分:0)

谢谢大家的非常明确和有益的答案! 我想我现在已经理解了事实,但我也得到了一些有用的提示,指出了我还不知道的ECMAScript细节。我需要更多地深入了解文献。 再次感谢你!汤姆