簡體   English   中英

JavaScript:X.prototype.x也將x添加到基類

[英]JavaScript: X.prototype.x adds x to base class, too

我精通C ++,所以我有很好的OOP背景,但我是JavaScript的新手,我正在努力了解如何在JavaScript中正確實現多態。 我已經閱讀了與此主題相關的一些教程和StackOverflow問題,但沒有一個詳細解釋了如何正確地從基類繼承並且還向子類添加新成員

function Obj1() {}
function Obj2() {}
function Obj3() {}

Obj2.prototype === Obj3.prototype;  // false

好奇心#1:如果Obj2Obj3 (以及Obj1 )繼承自Object ,為什么他們的原型不相同? Obj2Obj3各自都收到了自己的Object 副本嗎?

Obj2.prototype = Object;
Obj2.prototype = Object;
Obj2.prototype === Obj3.prototype;  // true
Obj2.prototype = Obj1;
Obj3.prototype = Obj1;
Obj2.prototype === Obj3.prototype;  // true

好奇心#2:在這兩種情況下, Obj2Obj3現在共享相同的原型。 發生了什么變化?

Obj2.prototype.pi = function() {  return 3.14159;  }
Obj2.prototype.pi();  // 3.14159
Obj3.prototype.pi();  // 3.14159
Obj1.pi();  // 3.14159

真實問題:改變Obj2的原型也改變了Obj3的原型和Obj1本身的功能。 這對於這個C ++程序員來說非常令人震驚,盡管它正是我對上述語法的預期:畢竟,由於Obj2Obj3的原型都與Obj1等同,對一個的改變將產生相同的變化。另外兩個。 不過,我想用Obj1作為既是一個基類Obj2Obj3 ,並插入一個新的功能Obj2以任何方式通過共享Obj1Obj3 我怎么做?

當這些對象被實例化時,會出現更多的好奇心

var x = new Obj2();
x.pi();  // 3.14159
var y = new Obj3();
y.pi();  // 3.14159
var z = new Obj1();
z.pi();  // Error: pi() not defined on z.

Obj2Obj3都有一個函數pi() ,這意味着它們仍然共享一個包含函數pi()基類 這個基類莫屬Obj1 -但實例Obj1 包含pi()盡管有相反的證據!

在你的第一個證明中:

function a () {};
function b () {};

a.prototype === b.prototype; // false

您正在研究prototype不是Object的事實 - 它不是基類。 它是一個對象,然后通過Object的方法和屬性進行原型擴展。
任何{} === {};測試{} === {}; 是否會返回一個錯誤, 總是 ,除非你正在測試兩個指針指向同一個對象:

var a = {},
    b = a;

a === b; // true

之后你的繼承訓練直接指向缺少這個概念,因為你已經將所有三個函數設置為指向同一個對象(最初是Object本身,然后是Obj1的原型對象)。
prototype實時的,在對象構造之后,對原型的任何更改都將反映在包含指向該對象的指針的對象中。

你已經給Obj1Obj2Obj3指向了完全相同的對象。
因此,當你試圖訪問一個屬性時(而不是生活在一些靜態的,預編譯的,GOTO中),所有對它們共享的原型對象的任何修改都將反映在它們所有構造的對象中,因為繼承解析是實時發生的。州)。

如果你想要子類的能力,你可以做這樣的事情:

var A = function () {};
A.prototype.foo = function () {};
var a = new A();

var B = function () {};
B.prototype = a; // or new A(); -- an object which can live-lookup the prototype of A
// problem is, `constructor` on the prototype will now point to `A`, so...
B.prototype.constructor = B; // now b instanceof B should work in tests
B.bar = function () {};


var b = new B();
b.foo(); // A.prototype.foo
b.bar(); // B.prototype.bar

但實際上,如果你試圖將這一點擴展得太遠,那么你會讓自己變得瘋狂。
在JS中遵循的更合理的路徑是基於組件的對象構造和依賴注入。

prototype屬性也返回一個對象,它是一個對象的實例,但不是同一個實例,因此它們不是同一個對象,並且相等的比較自然會返回false。

更詳細地說,Obj1,Obj2和Obj3都是函數和對象,它們的原型也是對象。 在C ++術語中,將prototype屬性視為指向另一個對象的指針,而不是類定義或基類。

在Obj2的情況下,您將聲明一個單獨的方法,如下所示:

function Obj2() {
    this.prototype = new Obj1();
    this.myOwnMethod = function (x) { ... }
}

我試圖用自己的語言寫出Javascript中對象方向的一個很好的解釋,但我認為這需要太長時間:)而我決定刪除我寫的半連貫文本,並給出兩個指示,幫助我理解它更深入,希望他們也會幫助你:

使用emberbackbone或其他框架為您提取此信息。 要像你期望的那樣繼承工作需要很多工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM