gpt4 book ai didi

javascript - 向没有 .prototype 的构造函数添加新属性

转载 作者:可可西里 更新时间:2023-11-01 01:20:25 25 4
gpt4 key购买 nike

当我有我想用作构造函数的函数时,请说:

function clog(x){
var text = x;
return console.log(text );
}

我已经做了一些实例
var bla = new clog();

现在我想添加新功能,所以我会使用
clog.prototype.alert = alert(text);

如果我只是这样做会有什么区别:
clog.alert = alert(text);

这不会被 clog 的对象继承吗?是他们的原型(prototype)吗?

最佳答案

由构造函数创建的实例(在您的情况下为 clog)继承对 clog.prototype 的引用。目的。因此,如果您将属性添加到 clog.prototype ,它将显示在实例上。如果您向 clog 添加属性本身,它不会出现在实例上。

您引用的代码存在一些问题,因此让我们看一个抽象示例:

function Foo() {
}
Foo.prototype.bar = "I'm bar on Foo.prototype";
Foo.bar = "I'm bar on Foo";

var f = new Foo();
console.log(f.bar); // "I'm bar on Foo.prototype"
// E.g., `f` inherits from `Foo.prototype`, not `Foo`

// And this link is live, so:
Foo.prototype.charlie = "I'm charlie on Foo.prototype";
console.log(f.charlie); // "I'm charlie on Foo.prototype";

从你下面的评论:

I don't understand why new properties added directly to Foo would be ignored by the prototype chain?



因为它是 Foo.prototype ,不是 Foo ,这是通过 new Foo() 创建的对象的原型(prototype).

isn't prototype simply points to the constructor object?



不, FooFoo.prototype是完全不同的对象。 Foo是一个函数对象,它像所有函数对象一样可以有属性。 Foo之一的属性是 prototype ,这是一个非函数对象,除了 constructor 之外最初是空白的指向 Foo 的属性.它是 Foo.prototype ,不是 Foo ,通过 new Foo 创建的实例得到他们的原型(prototype)。 Foo的唯一作用是创建使用 Foo.prototype 的对象。作为他们的原型(prototype)。 (实际上,在 Foo 的情况下,它只是初始化这些对象;它们由 new 运算符创建。使用像 Foo 这样的传统函数, new 创建对象。如果此代码使用 ES2015+ class 语法, new 不会创建对象,它将留给 Foo [如果 Foo 是基类构造函数] 或 Foo 的最终基类 [如果 Foo子类构造函数]。)

If I do Foo.newProp = "new addition" why is f.newProp => undefined?



(为了避免混淆,我将上面的 Foo.new = ... 更改为 Foo.newProp = ...,因为 new 是一个关键字。虽然您可以像在 ES5 中那样使用它,但最好不要这样做。)

因为 Foo.newPropf 几乎没有任何关系.您可以在 f.constructor.newProp 上找到它, 自 f.constructorFoo .

一些 ASCII 艺术:

鉴于此代码:
function Foo() {
}
Foo.prototype.bar = "I'm bar on Foo.prototype";
Foo.bar = "I'm bar on Foo";

我们有这些具有这些属性的对象(为清楚起见省略了一些):
        +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+        |                                       |        V                 +−−−−−−−−−−−−−−−−−−+  |+−−−−−−−−−−−−−−−−+    +−−>| [String]         |  || Foo [Function] |    |   +−−−−−−−−−−−−−−−−−−+  |+−−−−−−−−−−−−−−−−+    |   | "I'm bar on Foo" |  || bar            |−−−−+   +−−−−−−−−−−−−−−−−−−+  || prototype      |−−−−+                         |+−−−−−−−−−−−−−−−−+    |                         |                      +−−−−−−−−−−+              |                                 |              |                                 V              |                               +−−−−−−−−−−−−−+  |                               | [Object]    |  |                               +−−−−−−−−−−−−−+  |                               | constructor |−−+   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−+                               | bar         |−−−−−>| [String]                   |                               +−−−−−−−−−−−−−+      +−−−−−−−−−−−−−−−−−−−−−−−−−−−−+                                                    | "I'm bar on Foo.prototype" |                                                    +−−−−−−−−−−−−−−−−−−−−−−−−−−−−+

Now if we do

var f = new Foo();

我们有( 粗体 中的新内容):
        +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+        |                                          |        V                 +−−−−−−−−−−−−−−−−−−+     |+−−−−−−−−−−−−−−−−+    +−−>| [String]         |     || Foo [Function] |    |   +−−−−−−−−−−−−−−−−−−+     |+−−−−−−−−−−−−−−−−+    |   | "I'm bar on Foo" |     || bar            |−−−−+   +−−−−−−−−−−−−−−−−−−+     || prototype      |−−−−+                            |+−−−−−−−−−−−−−−−−+    |                            |                      +−−−−−−−−−−−−−+              |                                    |              |                                    V              |+−−−−−−−−−−−−−−−+                 +−−−−−−−−−−−−−+  || f [Object]    |          +−−−−−>| [Object]    |  |+−−−−−−−−−−−−−−−+          |      +−−−−−−−−−−−−−+  || [[Prototype]] |−−−−−−−−−−+      | constructor |−−+  +−−−−−−−−−−−−−−−−−−−−−−−−−−−−++−−−−−−−−−−−−−−−+                 | bar         |−−−−>| [String]                   |                                  +−−−−−−−−−−−−−+     +−−−−−−−−−−−−−−−−−−−−−−−−−−−−+                                                      | "I'm bar on Foo.prototype" |                                                      +−−−−−−−−−−−−−−−−−−−−−−−−−−−−+

([[Prototype]] is an object's internal field referring to its prototype. This is accessible via Object.getPrototypeOf [or __proto__ on JavaScript engines on web browsers, but don't use __proto__, it's just for backward compatibility with old SpiderMonkey-specific code.)

Now suppose we do this:

f.charlie = "I'm charlie on f";

所有改变的是 f对象( 粗体 中的新内容):
        +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+        |                                          |        V                 +−−−−−−−−−−−−−−−−−−+     |+−−−−−−−−−−−−−−−−+    +−−>| [String]         |     || Foo [Function] |    |   +−−−−−−−−−−−−−−−−−−+     |+−−−−−−−−−−−−−−−−+    |   | "I'm bar on Foo" |     || bar            |−−−−+   +−−−−−−−−−−−−−−−−−−+     || prototype      |−−−−+                            |+−−−−−−−−−−−−−−−−+    |                            |                      +−−−−−−−−−−−−−+              |                                    |              |                                    V              |+−−−−−−−−−−−−−−−+                 +−−−−−−−−−−−−−+  || f [Object]    |          +−−−−−>| [Object]    |  |+−−−−−−−−−−−−−−−+          |      +−−−−−−−−−−−−−+  || [[Prototype]] |−−−−−−−−−−+      | constructor |−−+  +−−−−−−−−−−−−−−−−−−−−−−−−−−−−+| charlie       |−−−−−−−−−−+      | bar        |−−−−−>| [String]                   |+−−−−−−−−−−−−−−−+          |      +−−−−−−−−−−−−−+     +−−−−−−−−−−−−−−−−−−−−−−−−−−−−+                           |                          | "I'm bar on Foo.prototype" |                           |                          +−−−−−−−−−−−−−−−−−−−−−−−−−−−−+                           |                           |      +−−−−−−−−−−−−−−−−−−−−+                           +−−−−−>| [String]           |                                  +−−−−−−−−−−−−−−−−−−−−+                                  | "I'm charlie on f" |                                  +−−−−−−−−−−−−−−−−−−−−+

f now has its own property, called charlie. This means that these two statements:

console.log(f.charlie); // "I'm charlie on f"
console.log(f.bar); // "I'm bar on Foo.prototype"

处理方式略有不同。

我们来看 f.charlie第一的。这是引擎如何处理 f.charlie :
  • 是否f有自己的属性叫做 "charlie" ?
  • 是的;使用该属性的值。

  • 足够简单。现在让我们看看引擎如何处理 f.bar :
  • 是否f有自己的属性叫做 "bar" ?
  • 不;是否f有原型(prototype)吗?
  • 是的;是否f的原型(prototype)有一个名为 "bar" 的属性?
  • 是的;使用该属性的值。

  • 所以 f.charlie之间有很大的区别和 f.bar : f有它的 自己的 名为 charlie 的属性,但是一个 继承名为 bar 的属性.如果 f的原型(prototype)对象没有名为 bar 的属性,它的原型(prototype)对象(在这种情况下, Object.prototype )将被检查,依此类推,直到我们用完原型(prototype)。

    顺便说一句,您可以使用 hasOwnProperty 测试一个属性是否是“自己的”属性。所有对象都具有的功能:
    console.log(f.hasOwnProperty("charlie")); // true
    console.log(f.hasOwnProperty("bar")); // false

    从评论中回答您的问题:

    I make function Person(first_name, last_name) {this.first_name = first_name; this.last_name = last_name;} and then var ilya = new Person('ilya', 'D') how does it resolves the inner name properties?



    内拨打 Person这是 new Person(...) 的一部分表达式, this new返回的新生成的对象表达。所以当你做 this.prop = "value"; ,您直接在该对象上放置一个属性,与原型(prototype)无关。

    换句话说,这两个例子的结果是 正好一样 p目的:
    // Example 1:
    function Person(name) {
    this.name = name;
    }
    var p = new Person("Fred");

    // Example 2:
    function Person() {
    }
    var p = new Person();
    p.name = "Fred";

    以下是我提到的引用代码的问题:

    第一期:从构造函数返回一些东西:
    function clog(x){
    var text = x;
    return console.log(text ); // <=== here
    }

    99.9999% 的情况下,您不想从构造函数中返回任何内容。的方式 new操作工程是:
  • 创建一个新的空白对象。
  • 它从构造函数的 prototype 中获得了一个原型(prototype)。属性(property)。
  • 构造函数的调用使得 this指向新对象。
  • 如果构造函数不返回任何东西,或者返回对象以外的东西,new 的结果expression 是在步骤 1 中创建的对象。
  • 如果构造函数返回一个对象,结果new操作是那个对象。

  • 所以在你的情况下,因为 console.log不返回任何内容,您只需删除 return代码中的关键字。但是如果你使用了 return xyz();用一个返回对象的函数构造,你会弄乱你的构造函数。

    第 2 期:调用函数而不是引用它们

    在这段代码中:
    clog.prototype.alert = alert(text);

    你是 调用 alert函数并将其结果分配给名为 alert 的属性在 clog.prototype .自 alert不返回任何内容,它完全等同于:
    alert(text);
    clog.prototype.alert = undefined;

    ……这可能不是你的意思。也许:
    clog.prototype.alert = function(text) {
    alert(text);
    };

    在那里我们创建了一个函数并将对它的引用分配给 alert原型(prototype)上的属性。当函数被调用时,它会调用标准 alert .

    第 3 期:构造函数最初应该被封顶

    这只是风格,但它是 绝大多数标准:构造函数(用于 new 的函数)应该以大写字母开头,所以 Clog而不是 clog .不过,这只是风格。

    关于javascript - 向没有 .prototype 的构造函数添加新属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9582341/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com