【问题标题】:JavaScript - The Good Parts: Function prototypes vs Object prototypesJavaScript - 好的部分:函数原型与对象原型
【发布时间】:2014-01-24 00:08:40
【问题描述】:

刚读完“JavaScript: The Good Parts”——很棒的书。但是我对第 33-34 页上的一个非常重要的主题感到困惑 - 增强类型。它描述了添加到 Function.prototype 的新方法的创建,因此当使用新方法调用时,所有函数都将具有该方法可用。很公平。但随后的示例显示此方法用于数字和字符串。我在想,是对象而不是函数。我在这里错过了什么?

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};

使用示例:

Number.method('integer', function() {
    return Math[this < 0 ? 'ceiling' : 'floor'](this);
});

document.writeln((-10 / 3).integer()); //-3

【问题讨论】:

  • 函数是对象。
  • @MattBall 我认为这不是 OP 的要求。相反,我认为他/她在问Number 是如何从Function 派生的。
  • 数字一个函数。它不是从函数“派生”出来的。这是一个实例。
  • @Pointy, Object.getPrototypeOf(Number) == Function.prototype // true
  • @JukkaP 没错,就是一个 Function 实例。

标签: javascript


【解决方案1】:

函数对象与函数实例对象

首先,在javascript中,函数也是对象。由此,我的意思不是由 new () 构造创建的对象,而是函数本身。为避免混淆,我将此类对象称为 Function object,将使用函数的 new () 构造创建的对象称为 Function instance object

_proto_和原型属性

javascript中的任何函数对象都有两个属性:_proto_prototype。此外,任何函数实例对象(使用新构造函数创建)都有一个属性 _ proto _ _ proto _ 定义了继承。可以在

找到一些很好的资源

http://zeekat.nl/articles/constructors-considered-mildly-confusing.html

继承是如何定义的?

如果objA和objC通过任意数量的_proto_连接,则一个对象objA继承另一个对象objC。所以如果objA的_proto_等于objB,objB的_proto_等于objC,那么objA继承objB和objC,而objB继承objC。

什么是继承?

这意味着任何继承对象都可以使用被继承对象的任何属性。

什么是 Function.prototype

是每个函数对象_proto_所引用的对象。这意味着每个 Function 对象 都可以访问 Function.prototype 的属性,因为每个 Function 对象 都继承了 Function.prototype 对象。这也意味着,如果 方法 属性被添加到 Function.prototype 对象中,它将可用于 javascript 中所有可能的 Function 对象。这包括字符串、数字等。

this.prototype[name] = func;

this 指的是 Function 对象,当“方法”从 Function 对象s(如 Number、String 等)调用时。这意味着我们现在在函数对象,名称为“name”,其函数为“func”。

Function object

prototype属性有什么用

函数对象原型函数实例对象_proto_引用使用该函数的新构造创建。

如果执行了以下操作:

Number.method('integer', function () {...});

然后 Number.prototype 在其中定义了 integer 方法。这意味着每个 Number 函数实例对象,例如new Number (2.4),将从 Number.prototype 中“继承”这个新属性 'integer',因为 Number function instance object 将其 _ proto _ 设置为 Number .prototype。

【讨论】:

    【解决方案2】:

    您向Number 原型添加一个方法,因此每个 Number instance 都可以访问它。换句话说,因为 Number 原型上有一个名为“integer”的属性,所以从任何 Number 实例访问该属性的任何尝试都会成功。这就是将属性放在构造函数原型上的全部意义所在。

    当 JavaScript 原始数字出现在 . 运算符的左侧时,该语言会自动将其封装在 Number 实例中,以便方法调用有意义。

    edit — 让我们看看这个“方法”函数是如何工作的。在通话中

    Number.method( "integer", function() { ... } )
    

    发生了什么事?那么,在“method”函数内部,“name”参数是“integer”。然后将函数参数分配为this.prototype 的属性。在“方法”函数的调用中,this 是什么?它是 Number 构造函数。因此,“方法”函数——它位于 Function 原型上,因此可用于所有函数实例,例如 Number 构造函数——将给定函数添加为所涉及的构造函数原型的属性。

    为什么“方法”属性作为 Number 构造函数的属性可见?因为 Number 构造函数本身就是一个函数。 “方法”函数是作为 Function 原型的属性创建的,这意味着它对每个函数实例都是可见的——包括 Number 构造函数。

    【讨论】:

    • 是的,但是当 'method' 被添加到 Function.prototype 时,它​​是如何添加到 Number 原型中的?我可以理解是否将“方法”添加到 Object.prototype 中。
    • @svenyonson Number 是一个函数。在浏览器控制台中试试这个:typeof Number
    • @svenyonson 正如 Matt Ball 所说,Number 构造函数本身就是一个函数实例。
    • @Pointy - 我想我现在明白了。 (-10/3) 表达式必须调用 Number 构造函数。
    • @svenyonson 是的,完全正确!! JavaScript 既简单又复杂 :)
    【解决方案3】:

    NumberObject 或其他内置类也是构造函数,那么构造函数是JavaScript 中的函数。 ECMAScript 规范中有两个重要的描述:

    每个内置函数和每个内置构造函数都有 Function 原型对象,它是表达式 Function.prototype (15.3.4) 的初始值,作为其 [[Prototype]] 内部属性的值。

    除非另有说明,否则每个内置原型对象都有 Object 原型对象,它是表达式 Object.prototype (15.2.4) 的初始值,作为其 [[Prototype]] 内部属性的值,除了对象原型对象本身。

    所以在控制台中,我们可以执行代码:

    Number.prototype.__proto__.isPrototypeOf(Function)

    结果是true

    Number可以访问Function.prototype的方法是合理的。

    同时,如果我们将Object.prototype扩展为Object.prototype.say = 'hello';,我们也可以将say属性访问为Function.say

    因为Function.prototype.isPrototype(Object)true

    【讨论】:

      【解决方案4】:

      这个恶魔你能看出清楚和明显的区别吗

      [**

      在此处输入图片描述 **]2

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多