ECMA-5是否存在新类型的运算符(或函数)?

时间:2012-11-01 02:38:38

标签: javascript ecmascript-5

我认为JavaScript有5种基本类型(null,undefined,boolean,number,string),然后有对象(包括数组,函数和自定义的伪类对象)。但是有点奇怪

typeof null

"object",并且没有简单的方法来取回伪经典类的对象类名称,例如PersonAuthor。我想知道是否有一个更新的运算符或函数可以为原始类型返回可能的小写名称("null"null而不是"object"),以及自定义伪的大写情况 - 经典物品?

如果ECMA-5或更高版本中不存在此类操作员或功能,是否有意义?否则,我们可能需要依赖于我们自己的定义或任何框架,但这不会是跨不同平台的标准。

3 个答案:

答案 0 :(得分:3)

ECMAScript 5对象具有称为[[Class]]的内部属性。这是ES5中最接近你要求的东西。您可以使用[[Class]]访问Object.prototype.toString,如下所示:

function getClassOf(obj) {
    return Object.prototype.toString.call(obj).slice(8, -1);
}

getClassOf([ ]); // => "Array"
getClassOf(new Date()); // => "Date"
getClassOf(function() { }); // => "Function"
getClassOf(3); // => "Number"
getClassOf(true) // => "Boolean"
getClassOf(document.createElement('div')); // => "HTMLDivElement"
getClassOf(Math); // => "Math"
getClassOf(null); // => "Null"
getClassOf(undefined); // => "Undefined"
getClassOf({ x: 1 }); // => "Object"

此行为对于充分识别来自其​​他帧的对象至关重要。

但是,它不适用于用户定义的构造函数。使用用户定义的构造函数创建的对象具有[[Class]] "Object"

function Foo() { }
var foo = new Foo();

getClassOf(foo); // => "Object"

看起来ECMAScript 6可以扩展Object.prototype.toString返回的内容,以便getClassOf(foo)可以通过"Foo"符号@@toStringTag

有关即将推出的标准的更多信息,请参阅https://mail.mozilla.org/pipermail/es-discuss/2012-September/025344.html


你可以创建自己的功能来做你想做的事情:

function getTypeOf(value) {

    // Return "null" for null.
    if (value === null) return 'null';

    // Return primitive types.
    var type = typeof value;
    if (type != 'object') return type;

    // Return [[Class]] if available for objects.
    type = Object.prototype.toString.call(value).slice(8, -1);
    if (type != 'Object') return type;

    // Return "Object" if it wasn't created with another constructor.
    var proto = Object.getPrototypeOf(value);
    if (proto == Object.prototype)
        return 'Object';

    // Return the constructor name if constructor hasn't been
    // modified on the object.
    if (value.constructor && proto === value.constructor.prototype)
        return value.constructor.name;

    // Return the constructor name if constructor hasn't been
    // modified on the prototype.
    if (proto.constructor && proto === proto.constructor.prototype)
        return proto.constructor.name;

    // Return "???" if the type is indeterminable.
    return '???';

}

示例:

getTypeOf([ ]); // => "Array"
getTypeOf(new Date()); // => "Date"
getTypeOf(function() { }); // => "Function"
getTypeOf(3); // => "number"
getTypeOf(true) // => "boolean"
getTypeOf(document.createElement('div')); // => "HTMLDivElement"
getTypeOf(Math); // => "Math"
getTypeOf(null); // => "null"
getTypeOf(undefined); // => "undefined"
getTypeOf({ x: 1 }); // => "Object"

function Foo() { }
var foo = new Foo();

getTypeOf(foo); // => "Foo"

// If the constructor property is changed, still works.
foo.constructor = function FakeConstructor() { };
getTypeOf(foo); // => "Foo"

// If the constructor property AND the prototype's constructor is
// changed, result is "???".
foo.constructor = function FakeConstructor() { };
Foo.prototype.constructor = function FakeConstructor2() { };
getTypeOf(foo); // => "???"

答案 1 :(得分:1)

typeof的行为由规范section 11.4.3决定,表20:

  

表20 - 运营商结果类型

Type of val                      Result
-----------------------------------------------------------------------------------
Undefined                        "undefined"
-----------------------------------------------------------------------------------
Null                             "object"
-----------------------------------------------------------------------------------
Boolean                          "boolean"
-----------------------------------------------------------------------------------
Number                           "number"
-----------------------------------------------------------------------------------
String                           "string"
-----------------------------------------------------------------------------------
Object (native and does not 
implement [[Call]])              "object"
-----------------------------------------------------------------------------------
Object (native or host 
and does implement [[Call]])     "function"
-----------------------------------------------------------------------------------
Object (host and does not        Implementation-defined except may not be 
implement [[Call]])              "undefined", "boolean",  "number", or "string".

(大写Null是一种内部类型,其唯一值为null。)

这似乎只是一个惯例; null instanceof Objectfalse,因此,正如预期的那样,null显然不是一个对象。

您要求的运营商不存在。要确定名称,您可以使用=== null来测试null,并使用typeof来测试其他基元。至于“自定义伪古典对象”,您可以使用的工具是:

(从this question列出,您可以在其中看到一些示例。)

答案 2 :(得分:0)

您现在可以在所有浏览器中执行此操作。

任何对象的constructor属性都将返回拥有该对象原型的函数。

function Person() { }
alert(new Person().constructor === Person) //true