为啥 4 不是 Number 的实例?
Posted
技术标签:
【中文标题】为啥 4 不是 Number 的实例?【英文标题】:Why is 4 not an instance of Number?为什么 4 不是 Number 的实例? 【发布时间】:2010-10-03 02:42:20 【问题描述】:只是好奇:
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,如果我不能,我认为它是可用的。
【参考方案1】:
value instanceof Constructor
与 Constructor.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 定义了以下原始类型:Undefined、Null、Boolean、Number 和 字符串。此外,对于具有属性的事物,还有类型 Object。
例如,函数是 Object 类型的(它们只是有一个特殊的属性称为 [[Call]]),而null
是 Null类型的原始值>。这意味着typeof
运算符的结果并没有真正返回值的类型...
此外,JavaScript 对象还有另一个称为 [[Class]] 的属性。您可以通过Object.prototype.toString.call(value)
获取它(这将返回'[object
Classname
]'
)。数组和函数的类型是 Object,但它们的类是 Array 和 Function。
当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
类型,而是object
。 new
运算符总是产生一个对象。我看到这样的事情:
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
方法也可以帮助您。
【讨论】:
以上是关于为啥 4 不是 Number 的实例?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我不能使用常量而不是 this.item.number?
为啥 Number.MAX_SAFE_INTEGER 是 9,007,199,254,740,991 而不是 9,007,199,254,740,992?