'原型的作用'在`function`类型对象的设计中的属性?

时间:2015-09-11 10:23:13

标签: javascript prototypal-inheritance

根据理解,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语法了解基于类的继承,其中可以继承静态/实例成员。

3 个答案:

答案 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不是基于类的。 只有对象和继承。

现在,让我们看一下对象图。

enter image description here

请注意,new Number 会继承Number

prototypeconstructor都不是继承关系。

这意味着数字实例会继承toExponentialtoFixed等,但不会继承parseFloatparseInt等。 因此,您可以将其称为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没有将isFiniteisNaN放到Number.prototype

为什么没有浏览器在toFixed上实现Number哪个可以与Number.prototype上的gem_install_path/mygem/lib/mygem.rb共存,在我们现在知道的第一次形成JavaScript的浏览器大战期间?

语言设计是一门艺术。 而且你可能并不总是知道谁应该负责或为什么,因为它已被许多人塑造。