根据理解,prototype
类型对象中存在function
属性的主要目的是允许位于prototype
下的属性/方法被其他对象继承。这可以实现原型继承。
考虑window['Number']
函数类型对象,
一般而言,Idea是理解prototype
下的内容的思维过程。所以。我想举一个具体的例子,即Number
,问题如下。
从设计角度来看,我将如何理解,
1)
为什么parseFloat()
/ parseInt()
/ isFinite()
/ isInteger()
/ isFinite()
/ isNaN()
/ NEGATIVE_INFINITY
/ {{1} }
是NaN
类型对象function
的一部分?
2)
为什么方法Number
/ toExponential()
/ toFixed()
是toPrecision()
个对象的一部分?
注意:使用java语法了解基于类的继承,其中可以继承静态/实例成员。
答案 0 :(得分:1)
如果您了解基于经典类的继承,那么Number.parseFloat
是静态类方法,而Number.prototype.toFixed
是实例方法。 “类方法”不需要Number
的实例,您可以直接将它们称为Number.parseFloat(foo)
。另一方面,实例方法首先需要一个实例:
var foo = new Number(bar);
foo.toFixed();
答案 1 :(得分:1)
在原型对象上声明的属性在所有实例中都可见。因此:
var n1 = new Number(1), n2 = new Number(2);
这是Number的两个实例,并且通过每个实例,可以调用Number原型上的函数:
alert( n2.toExponential() ); // "2e+0"
由于函数调用在JavaScript中的工作方式,该示例中的.toExponential()
函数将使用this
调用,引用用于进行函数调用的数字实例 - n2
在这种情况下。
现在,.toExponential()
函数可以被定义为Number构造函数本身的属性,但是必须显式传递参数(如Number.toExponential(2)
) 。然而,这不是运行时的设计方式。和那么多“为什么?”一样关于语言和API如何工作的问题,它最终只是语言设计者的设计偏好。应该很清楚像.parseFloat()
这样的东西真的不作为原型方法有意义,因为.parseFloat()
的全部要点是转变不是< / em>一个数字到一个数字。 (它可能被添加到一个或多个其他原型对象中,但语言设计者的偏好再次只是使它成为Number构造函数本身的可调用函数;这是最近的ES6添加到规范当然。)
最后请注意,在Number构造函数的特定情况下,实际上显式实例化一个数字对象是非常罕见的。通常,当数字原始值与.
或[ ]
运算符一起使用时,就会隐式发生,就像它是对象引用一样。基元是不是对象,但在这些情况下,语言会自动将原始值包装在Number对象中,因此如果它是这样写的,上面的第一个示例将是相同的:
var n2 = 2;
alert(n2.toExponential());
变量n2
中有一个普通的原始2
,但它将被包装在一个Number实例中,以便允许方法调用。
答案 2 :(得分:0)
我不知道你是指程序设计视角还是语言(核心库)设计视角,所以我会尝试回答这两个问题。
在我们开始之前,请忘记&#34; class&#34;或&#34;实例&#34;或&#34;静态&#34;。 JavaScript不是基于类的。 只有对象和继承。
现在,让我们看一下对象图。
请注意,new Number
不会继承Number
。
prototype
和constructor
都不是继承关系。
这意味着数字实例会继承toExponential
,toFixed
等,但不会继承parseFloat
,parseInt
等。
因此,您可以将其称为Number.parseFloat()
和new Number(n).toFixed()
。
这就是JS的设计方式。如果您不喜欢它,您可以设计自己的数字库。
例如,您可以在Number对象上创建自己的Number,而不是在其原型对象上使用固定方法,如下所示:
var SheepyNumber = {
toFixed: ( n ) => Number.toFixed( n )
}
SheepyNumber.toFixed( 3.14159265358979323846 ) // Evaluates to '3'
不要将
toFixed
添加到Number
对象。它可能现在有用, 但是如果以后的规范引入了这个函数,其中任何参数或逻辑不同, 那么当你使用标准实现时你的程序可能会中断, 如果您保留自己的实施,或者第三方库可能会中断。 无论哪种方式,你输了。
这给我们留下了一个问题,为什么JS不像我们刚才那样将toFixed
放到Number
,而是将toFixed
放到Number.prototype
?
显而易见的答案是,这更加面向对象。
由于new Number
具有内部value
属性,toFixed
可以获取该值,而不是接受额外的参数。
真正的答案是没有人知道。
JavaScript为其核心API复制了Java - 您可以在Java Float类中找到大多数这些方法。
其中一些Java方法是instance methods(对应于Number.prorotype
上的方法),有些是static(对应于Number
上的方法),但大多数都< / em> - 包括a counterpart toFixed。
为什么JavaScript没有将isFinite
或isNaN
放到Number.prototype
?
为什么没有浏览器在toFixed
上实现Number
哪个可以与Number.prototype
上的gem_install_path/mygem/lib/mygem.rb
共存,在我们现在知道的第一次形成JavaScript的浏览器大战期间?
语言设计是一门艺术。 而且你可能并不总是知道谁应该负责或为什么,因为它已被许多人塑造。