gpt4 book ai didi

javascript - 为什么需要原型(prototype)对象(在函数中)?

转载 作者:行者123 更新时间:2023-12-03 14:13:15 26 4
gpt4 key购买 nike

我已经阅读了大量有关原型(prototype)的 Material ,并且总体上理解了继承。
但是,这是困扰我的一件事,我无法弄清楚。
dmitrysoshnikov.com有一个简化的示例说明如何使用以下代码段实现原型(prototype)继承:

// Generic prototype for all letters.
let letter = {
getNumber() {
return this.number;
}
};

let a = {number: 1, __proto__: letter};
let b = {number: 2, __proto__: letter};
// ...
let z = {number: 26, __proto__: letter};

console.log(
a.getNumber(), // 1
b.getNumber(), // 2
z.getNumber(), // 26
);

下面是这张图
Figure 1
然而,当我们开始使用实际的继承结构(使用 new 关键字)时,它开始看起来像这样:
Figure 2
我明白它是如何工作的。我不明白的是为什么突然我们需要所有子实例都从中继承的 Letter.prototype 对象,而不是像上面的第一张图那样拥有它。对我来说,第一个例子似乎没有任何问题。
我能想到的一个潜在原因是实际方法允许在类中实现静态方法/属性。在上面的示例中,如果您要添加一个静态方法,那么它将是一个添加到 Letter 对象而不是 Letter.prototype 对象的函数。子对象 (a,b,z) 将无法访问该函数。
在第一个示例中,这种功能必须以不同的方式实现,但我仍然认为这不是创建新 Prototype 对象的充分理由。我认为这个静态方法特性可以在没有它的情况下实现。
我错过了什么吗?
编辑:
我认为有很多人试图解释我很感激的事情,但我不确定我的问题 为什么 javascript 运行时被设计为以一种方式而不是另一种方式运行 正确理解。
为了说明我的意思,我尝试了一些事情。

class Car{
method() {
console.log("hello")
}
}

myCar = new Car();

// First a few tests as expected
myCar.method() // works
console.log(myCar.method === Car.method) // False, JS doesn't work that way, ok...
console.log(myCar.method === Car.prototype.method) // This is how it works, fine...

// How about we move the reference to the method up one level
Car.method = Car.prototype.method

// Delete the reference to it in prototype object,
// Btw. I tried to remove reference to whole prototype but somehow doesn't let me
delete Car.prototype.method

// Change the prototype chain so it links directly to Car and not Car's prototype object
myCar.__proto__ = Car

myCar.method() // Still works!!!
console.log(myCar.method === Car.method) // True !
console.log(myCar.method === Car.prototype.method) // False, we deleted the method property out of Car.prototype

所以, Car.prototype不再需要,至少 myCar 的执行不需要。
那么为什么方法进入 Car.prototype而不是 Car然后为什么不 myCar.__proto__ = Car而不是 myCar.__proto__ = Car.prototype ?

最佳答案

I don't understand is why suddenly we need the Letter.prototype object from which all the child instances inherit from instead of having it like the first diagram above.


实际上那里没有任何改变。它仍然是同一个对象,与名为 const letter 的对象具有相同的目的。在第一个例子中。字母实例继承自它,它存储 getNumber方法,它继承自 Object.prototype .
改变的是额外的 Letter功能。

To me it didn't seem like anything was broken with the first example.


是的,它是: {number: 2, __proto__: letter}是创建实例的一种非常丑陋的方式,并且在必须执行更复杂的逻辑来初始化属性时不起作用。
解决此问题的一种方法是

// Generic prototype for all letters.
const letterPrototype = {
getNumber() {
return this.number;
}
};
const makeLetter = (number) => {
const letter = Object.create(letterPrototype); // {__proto__: letterPrototype}
if (number < 0) throw new RangeError("letters must be numbered positive"); // or something
letter.number = number;
return letter;
}

let a = makeLetter(1);
let b = makeLetter(2);
// ...
let z = makeLetter(26);

console.log(
a.getNumber(), // 1
b.getNumber(), // 2
z.getNumber(), // 26
);

现在我们有两个值, makeLetterletterPrototype不知何故属于彼此。此外,当比较各种 make…函数,它们都共享相同的模式,首先创建一个从各自原型(prototype)继承的新对象,然后在最后返回它。为了简化,引入了一个通用结构:

// generic object instantiation
const makeNew = (prototype, ...args) => {
const obj = Object.create(prototype);
obj.constructor(...args);
return obj;
}

// prototype for all letters.
const letter = {
constructor(number) {
if (number < 0) throw new RangeError("letters must be numbered positive"); // or something
letter.number = number;
},
getNumber() {
return this.number;
}
};

let a = makeNew(letter, 1);
let b = makeNew(letter, 2);
// ...
let z = makeNew(letter, 26);

console.log(
a.getNumber(), // 1
b.getNumber(), // 2
z.getNumber(), // 26
);
你能看到我们要去哪里吗? makeNew实际上是语言的一部分, new运算符(operator)。虽然这会起作用,但实际上为语法选择的是使 constructor传递给 new 的值原型(prototype)对象存储在 .prototype的构造函数。

关于javascript - 为什么需要原型(prototype)对象(在函数中)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65181599/

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