1

我很好奇这里发生了什么。如您所见,我定义了一个构造函数,调用range它来构建新range对象。我已经range通过它的原型扩展了构造函数,添加了一个简单的includes方法。我已经创建了我的新对象并使用了p. 当我尝试将此方法用于我的range对象时,一切都很好,并且可以按预期工作。问题是当我尝试查看p.prototype它时告诉我它的类型是未定义的并且p.prototype没有方法......嗯??

这里发生了什么??p一个对象如何,p.prototype又不是?

    function range(from, to) {
        this.from = from;
        this.to = to;
    }


    range.prototype = {
        includes: function(x) { return this.from <= x && x <= this.to; },
    }

    var p = new range(1, 4);

    console.log(typeof p) //outputs object
    console.log(typeof p.prototype) //outputs undefined

    console.log(Object.getOwnPropertyNames(range.prototype)); //outputs includes
    console.log(Object.getOwnPropertyNames(p.prototype)); //throws error, p.prototype is not an object
4

4 回答 4

2

问题是当我尝试查看p.prototype它时告诉我它的类型未定义

这是正确的。构造函数创建的对象range没有prototype属性,但它们有一个底层原型(从函数的prototype属性中提取range)。

让我们看看当你这样做时会发生什么new range()

  1. JavaScript 引擎创建一个新的空白对象。
  2. JavaScript 引擎将该对象的底层原型(而不是prototype)分配为 所引用的对象range.prototype。(在规范中,这个属性——它不能在代码中直接访问,但见下文——被称为[[Proto]]。)
  3. JavaScript 引擎range通过this引用新对象进行调用。
  4. 假设range不返回不同的对象(它可以这样做;这有点模糊),结果new range是在步骤 1 中创建的新对象。

稍后,当您使用 时this.includes,会发生以下情况:

  1. 引擎查看实际对象以查看它是否具有includes属性。
  2. 既然没有,引擎[[Proto]]就会查看是否有一个。
  3. 既然这样做了,它就会使用那个(如果没有,它会查看[[Proto]]'s[[Proto]]等等)。

这里的关键是:

  1. 对象具有底层原型,不能通过对象本身的任何命名属性访问。(事实上​​,过去我们根本无法使用它们现在,在 ES5 中,我们有Object.getPrototypeOf。)
  2. Objects created via new SomeFunctionName get their prototype from SomeFunctionName.prototype property, which is a perfectly normal property of the SomeFunctionName object (functions are first-class objects in JavaScript).

Side note: You're replacing the prototype of range with your code. In general, although it works, I would avoid that. Instead, augment the existing object referred to by range.prototype. (Add properties to it, rather than replacing it.) But that's not central to your question.

于 2012-11-03T23:37:51.897 回答
0

我想你想要的是:

range.prototype.includes = function(x) { 
    return this.from <= x && x <= this.to; 
}
于 2012-11-03T23:34:55.733 回答
0

您重新定义了原型对象,因此对原始对象的引用消失了。试试这个方法:

range.prototype.includes = function(x) { 
    return this.from <= x && x <= this.to;
}
于 2012-11-03T23:35:32.677 回答
0
Number.prototype.myRound = function (decimalPlaces) {
    var multiplier = Math.pow(10, decimalPlaces);

    return (Math.round(this * multiplier) / multiplier);
};
于 2013-12-20T07:33:24.267 回答