为什么 4 不是 Number 的实例?

IT技术 javascript
2021-02-06 17:40:11

只是好奇:

  • 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 也返回假
  • ('some string').toString instanceof String 也返回假

对于对象、数组或函数类型,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
5个回答

value instanceof Constructor是相同的Constructor.prototype.isPrototypeOf(value)和两者检查[[原型]] -的链value对于特定对象的出现次数。

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

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

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


关于 JavaScript 类型的更多信息:ECMA-262 定义了以下基本类型:UndefinedNullBooleanNumberString此外,对于具有属性的事物,还有对象类型

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

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

上面给出的对象类的测试在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;
    }
}

对于原语,它将小写形式返回它们的类型,对于对象,它将标题大小写形式返回它们的

例子:

  • 对于Number类型的 原语 (例如),它将返回,对于Number类的包装对象(例如),它将返回5'number' new Number(5)'Number'

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

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

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

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

您可以尝试评估:

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

正如 Christoph 的回答中所述,字符串和数字文字与 String 和 Number 对象不同。如果您在文字上使用任何 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 )

在原始数字的情况下,该isNaN方法也可以帮助您。

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

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

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

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