【问题标题】:Why is 4 not an instance of Number?为什么 4 不是 Number 的实例?
【发布时间】:2025-11-21 20:15:02
【问题描述】:

只是好奇:

  • 4 instanceof Number => false
  • new Number(4) instanceof Number => true?

这是为什么?与字符串相同:

  • 'some string' instanceof String 返回错误
  • new String('some string') instanceof String => 是的
  • String('some string') instanceof String 也返回 false
  • ('some string').toString instanceof String 也返回 false

对于对象、数组或函数类型,instanceof 运算符按预期工作。我只是不知道如何理解。

[新见解]

Object.prototype.is = function() {
        var test = arguments.length ? [].slice.call(arguments) : null
           ,self = this.constructor;
        return test ? !!(test.filter(function(a){return a === self}).length)
               : (this.constructor.name ||
                  (String(self).match ( /^function\s*([^\s(]+)/im )
                    || [0,'ANONYMOUS_CONSTRUCTOR']) [1] );
}
// usage
var Newclass = function(){};  // anonymous Constructor function
var Some = function Some(){}; // named Constructor function
(5).is();                     //=> Number
'hello world'.is();           //=> String
(new Newclass()).is();        //=> ANONYMOUS_CONSTRUCTOR
(new Some()).is();            //=> Some
/[a-z]/.is();                 //=> RegExp
'5'.is(Number);               //=> false
'5'.is(String);               //=> true

【问题讨论】:

  • 你必须使用Number.prototype.isPrototypeOf(inp) - 如果正确使用你的方式也可以:inp.constructor === Number;它可能会失败,因为constructor 只是原型的一个属性,可以被覆盖!
  • 我不确定我理解你所说的“可以被覆盖”是什么意思。这并不意味着我可以用其他构造函数覆盖构造函数(尝试过)。 Number.prototype.isPrototypeOf(4) 顺便返回 false,所以我不能用它来检查原始值的类型,对吗?
  • 这就是重点(原始!== 包装原始)!检查构造函数是危险的,因为obj['constructor'] = ??? 有效!我建议使用我的typeOf() 函数;要同等对待基元和包装基元,请使用 if(typeOf(x).toLowerCase() === 'string')
  • 根据我的经验,将任何内容分配给 Obj.constructor 不会更改其构造函数。事实上,这样的分配似乎根本没有任何作用。 ('hellowrld').constructor = Number 仍然返回带有 getType 的字符串。
  • 当然试过你的 typeOf ,是的,它适用于原始类型。我想要所有类型的 1 个函数,无论是否原始。将尝试破坏 getType,如果我不能,我认为它是可用的。

标签: javascript


【解决方案1】:

value instanceof ConstructorConstructor.prototype.isPrototypeOf(value) 相同,并且都检查 value 的 [[Prototype]] 链是否出现特定对象。

字符串和数字是原始值,不是对象,因此没有 [[Prototype]],因此只有将它们包装在常规对象中(称为“装箱”)才有效在 Java 中)。

另外,正如您所注意到的,String(value)new String(value) 做不同的事情:如果您在不使用 new 运算符的情况下调用内置类型的构造函数,它们会尝试转换('cast')特定类型的参数。如果您使用new 运算符,它们会创建一个包装器对象。

new String(value) 大致相当于Object(String(value)),其行为方式与new Object(String(value)) 相同。


更多关于 JavaScript 中的类型:ECMA-262 定义了以下原始类型:UndefinedNullBooleanNumber 字符串。此外,对于具有属性的事物,还有类型 Object

例如,函数是 Object 类型的(它们只是有一个特殊的属性称为 [[Call]]),而nullNull类型的原始值>。这意味着typeof 运算符的结果并没有真正返回值的类型...

此外,JavaScript 对象还有另一个称为 [[Class]] 的属性。您可以通过Object.prototype.toString.call(value) 获取它(这将返回'[objectClassname]')。数组和函数的类型是 Object,但它们的类是 ArrayFunction

instanceof 失败时(例如,当对象在窗口/框架边界之间传递并且不共享相同的原型时),上面给出的对象类的测试有效。


另外,您可能想查看typeof 的改进版本:

function typeOf(value) {
    var type = typeof value;

    switch(type) {
        case 'object':
        return value === null ? 'null' : Object.prototype.toString.call(value).
            match(/^\[object (.*)\]$/)[1]

        case 'function':
        return 'Function';

        default:
        return type;
    }
}

对于原语,它将以小写返回它们的类型,对于对象,它将以大写返回它们的 .

示例:

  • 对于 type Number 的原语(例如5),它将返回'number',用于的包装对象> 数字(如new Number(5)),会返回'Number'

  • 对于函数,它将返回'Function'

如果您不想区分原始值和包装对象(无论出于何种原因,可能是不好的原因),请使用typeOf(...).toLowerCase()

已知的错误是 IE 中的一些内置函数,当与某些 COM+ 对象一起使用时,这些函数被视为 'Object' 和返回值 'unknown'

【讨论】:

  • @annakata:检查 ECMA-262。这些类型称为 Undefined、Null、Boolean、Number、String 和 Object;不管typeof 返回什么...
  • @Christoph - 这非常重要,因为包装对象是大写的,而 typeofs 是小写的,没有其他东西可以访问。因此,约定和实践是指小写的数据类型,如下所示:developer.mozilla.org/En/JS/Glossary
  • @annakata: typeof 已损坏 - 它的返回值与实际类型无关!
  • 好吧,我猜你会遵循规范,而我会遵循实践,在这种情况下,我认为这是正确的。我认为引用具有相同格式的类型和包装对象是不明智的,但我不会进一步编辑您的帖子。
  • 我比赛Strings and numbers are primitive values, not objects and therefore don't have a [[Prototype]]示例:(new Number(123)).__proto__ == (123).__proto__; // true
【解决方案2】:

您可以尝试评估:

>>> typeof("a")
"string"
>>> typeof(new String("a"))
"object"
>>> typeof(4)
"number"
>>> typeof(new Number(4))
"object"

【讨论】:

    【解决方案3】:

    这是我发现的 Javascript 的细微差别。如果 LHS 不是 object 类型,instanceof of 运算符将始终导致 false。

    请注意,new String('Hello World') 不会导致 string 类型,而是objectnew 运算符总是产生一个对象。我看到这样的事情:

    function fnX(value)
    {
         if (typeof value == 'string')
         {
              //Do stuff
         }
    }
    fnX(new String('Hello World'));
    

    期望“Do Stuff”会发生,但它不会发生,因为值的类型是对象。

    【讨论】:

      【解决方案4】:

      正如 Christoph 的回答中所述,字符串和数字文字与字符串和数字对象不同。如果您在文字上使用任何 String 或 Number 方法,请说

      'a string literal'.length
      

      文字暂时转换为对象,方法被调用,对象被丢弃。
      与对象相比,文字有一些明显的优势。

      //false, two different objects with the same value
      alert( new String('string') == new String('string') ); 
      
      //true, identical literals
      alert( 'string' == 'string' );
      

      始终使用文字来避免意外行为!
      如果需要,可以使用 Number() 和 String() 进行类型转换:

      //true
      alert( Number('5') === 5 )
      
      //false
      alert( '5' === 5 )
      

      【讨论】:

        【解决方案5】:

        对于原始数字,isNaN 方法也可以帮助您。

        【讨论】:

          最近更新 更多