簡體   English   中英

javascript構造函數如何工作

[英]How do javascript constructors work

我正在閱讀面向初學者的MDN Javascript,也就是說您可以創建一個構造函數,然后基於該構造函數創建對象實例。 現在,您可以訪問在構造函數中定義的屬性和方法。 但是,然后他們繼續說,至少在我看來,對象實例只能使用構造函數原型屬性上定義的屬性和方法。 有人可以解決這個問題嗎,因為實例似乎可以在示例中未定義prototype屬性的情況下訪問它們。 謝謝

function Person(first, last, age, gender, interests) {
    this.name = {
        first,
        last
    };
    this.age = age;
    this.gender = gender;
    this.interests = interests;
    this.bio = function() {
        alert(this.name.first + ' ' + this.name.last + 
              ' is ' + this.age + ' years old.'+
              ' He likes ' + this.interests[0] +
              ' and ' + this.interests[1] + '.');
        };
        this.greeting = function() {
            alert('Hi! I\'m ' + this.name.first + '.');
        };
    }

    var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);

    person1['age']
    person1.interests[1]
    person1.bio()
    // etc.

構造函數的prototype屬性附帶的所有內容均在使用該構造函數創建的所有實例之間共享 在所有此類對象中,值均相同。

構造函數還可以將各個屬性附加到要創建的對象上。 這些特定於新實例,並且不共享。

因此,Javascript對象的工作方式與其他編程語言不同。 好吧,無論如何,大多數主流的。

這很重要-一個Javascript對象實際上只是一個字典(又名地圖)。 例如:

var x = {}; // creates a new blank object
x.something = 42; // creates a property on the object and assigns value to it
x['something'] = 15; // Alternate syntax. Assigns to the same property we just created.
x['yo, this is valid too!'] = true; // Yes, this is valid too.

明白了嗎? 它只是一本字典,您可以設置任何所需的內容。 並且也未設置-這就是delete運算符的作用。

那么那些構造函數和原型呢? 好吧,任何函數都可以用作構造函數。 當你像

var x = new foo();

真正發生的是,Javascript創建了一個新的空白對象,然后在將新創建的對象放入this同時調用foo() 瞧,看起來有點像構造函數。

實際上有一點需要說明的怪癖。 如果構造函數return一個sa值,則Javascript將使用該值而不是新創建的對象。 因此,如果您這樣做:

function foo() {
    this.meaning = 42;
}

var a = new foo();

然后a將包含Javascript為您創建的空白對象。 但是,如果您這樣做:

function foo() {
    this.meaning = 42;
    return {nope: 3};
}

var a = new foo();

然后a將包含{nope : 3}對象。 好的,但是很少使用。

無論如何,我們在哪里? 啊,是的,原型。 哦,等等,首先需要解釋另一件事。 在Javascript中, 一切都是對象。 因此,這些事情是完全有效的:

var a = 42;
var b = "hello, world";

a.foo = "yay";
b.bar = 10;

而且,只是為了真正打動您, 功能也是對象 可以說是頭等公民。 這都是有效的:

function foo() {
}

foo.bar = "baz";

var x = foo;

是的,您可以像對待其他任何對象一樣對待函數。 您可以將它們放在變量中,將它們傳遞給參數中的其他函數,為其分配和刪除任意屬性,然后對其進行命名。 這是其他語言中很少見的功能,因此,這可能是最難解決的問題。 我知道我一開始就很震驚。

現在我們可以討論原型。 您會看到,Javascript中的每個函數還具有一個特殊的神奇屬性,稱為prototype 默認情況下,它設置為空白對象。 但是您可以將其設置為另一個對象。 或者,您可以向現有的空白對象添加/刪除屬性。 這只是另一個對象,對此沒什么幻想。

此外,Javascript中的每個對象都有一個特殊的神奇屬性__proto__ 請記住,當你調用new foo()一個新的對象被創建並傳遞給foo()this 好吧,這個新對象的__proto__設置為foo.prototype

現在假設您這樣做:

function foo() {
    this.a = 42;
}

foo.prototype.b = 15;

var x = new foo();

如果您隨后輸入xax具有這樣的屬性,一切都很好。 但是,如果您輸入xbx沒有這樣的屬性,這就是發生魔術的地方。 Javascript自動檢查是否存在x.__proto__.b ,如果存在,則返回它! 如果沒有,它將檢查x.__proto__.__proto__.b等,直到它以__proto__ == null命中一個對象,然后放棄並返回undefined因為沒有這樣的屬性。

另一方面,當您現在執行此操作時:

x.b = "foobarbaz";

然后,直接在x對象上創建b屬性。 原型保持不變。

因此,這就是在Javascript中創建“繼承”的方式。 隨着原型。 它與典型的基於類的語言不同,但功能同樣強大。

還可以提及其他一些細微差別和技巧,以及大量示例來幫助您掌握所有這些內容,但是...今天我的果汁已經用光了。 :)這樣可以回答問題,並希望您對閱讀的其他任何教程有更多的了解。

朱爾斯是對的。

進一步詳細說明:您具有此構造函數。

function Person(first, last, age, gender, interests) {
    this.name = {
        first,
        last
    };
    this.age = age;
    this.gender = gender;
    this.interests = interests;
    this.bio = function() {
        alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
    };
    this.greeting = function() {
        alert('Hi! I\'m ' + this.name.first + '.');
    };
}

現在您可以創建它的實例了...

var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);
var person2 = new Person('Anne', 'Smith', 32, 'male', ['music', 'skiing']);

如果訪問原型並進行更改,則其他所有實例也將具有此更改。

person1.__proto__.attrX = "Hello World"
alert(person2.attX)

起初,所有這些Javascript原型繼承都可能非常令人困惑,但是實際上您幾乎不需要。 實際上,我什至不推薦它,因為它很容易弄亂。 例如,您可能有想法在JS中更改基本數據類型的原型。 例如這樣:

Person.__proto__.arguments = "";

這非常非常糟糕。 特別是如果您確實想這樣做:

Person.prototype.arguments = "";

如果您不了解原型和__proto__之間的區別。 它們在不同的觀點上基本相同。

  • __proto__引用實例的構造函數
  • 如果在構造函數上使用原型,原型也會做同樣的事情

但是,因為構造函數本身是函數的實例,所以如果直接在構造函數上調用__proto__,則將始終引用函數的構造函數。 因此,更改函數構造函數中的某些內容將更改帶有JS的所有函數,如果您更改了諸如參數之類的函數中不可或缺的內容,則可能會造成干擾。 如果您深入研究它,它會變得非常討厭。但是您可以避免這些事情。

javascript對象繼承關系

我昨天剛剛學習了javascript對象的繼承關系,並根據這個良好的描述制作了一個圖表。 希望對您有用。

暫無
暫無

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

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