日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

js实现html模板继承,理解JavaScript中的原型和继承

發布時間:2023/12/1 javascript 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 js实现html模板继承,理解JavaScript中的原型和继承 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文主要講了原型如何在JavaScript中工作,以及如何通過[Prototype]所有對象共享的隱藏屬性鏈接對象屬性和方法;以及如何創建自定義構造函數以及原型繼承如何工作以傳遞屬性和方法值。

介紹

JavaScript是一種基于原型的語言,這意味著對象屬性和方法可以通過具有克隆和擴展能力的通用對象共享。這被稱為原型繼承,與類繼承不同。在流行的面向對象編程語言中,JavaScript是相對獨特的,因為其他著名的語言,如PHP、Python和Java都是基于類的語言,它們將類定義為對象的藍圖。

在文中,我們將學習什么是對象原型,以及如何使用構造函數將原型擴展為新對象。我們還將學習繼承和原型鏈。

JavaScript原型

JavaScript中的每個對象都有一個稱為[[Prototype]]的內部屬性。我們可以通過創建一個新的空對象來演示這一點。let x = {};

這是我們通常創建對象的方法,但是請注意,另一種實現方法是使用對象構造函數:let x = new object()

包圍[[Prototype]]的雙方括號表示它是一個內部屬性,不能在代碼中直接訪問。

要找到這個新創建對象的[[Prototype]],我們將使用getPrototypeOf()方法。Object.getPrototypeOf(x);

輸出將由幾個內置屬性和方法組成。

輸出:{constructor: ?, __defineGetter__: ?, __defineSetter__: ?, …}

找到的另一種方法[[Prototype]]是通過__proto__財產。__proto__是一個公開[[Prototype]]對象內部的屬性。

需要注意的是,. _proto__是一個遺留特性,不應該在生產代碼中使用,而且它也不是在每個現代瀏覽器中都存在。但是,我們可以在本文中使用它來進行演示。x.__proto__;

輸出將與使用getPrototypeOf()相同。

輸出{constructor: ?, __defineGetter__: ?, __defineSetter__: ?, …}

重要的是JavaScript中的每個對象都有一個[[Prototype]],因為它為任何兩個或多個對象創建了鏈接的方法。

您創建的對象和內置對象(如Date和Array)一樣具有[[Prototype]]。可以通過prototype屬性將這個內部屬性從一個對象引用到另一個對象,我們將在本教程的后面看到這一點。

原型繼承

當您試圖訪問對象的屬性或方法時,JavaScript將首先搜索對象本身,如果沒有找到,它將搜索對象的[[Prototype]]。如果在查詢對象及其[[Prototype]]后仍然沒有找到匹配項,JavaScript將檢查被鏈接對象的原型,并繼續搜索,直到到達原型鏈的末端。

原型鏈的末尾是Object.prototype。所有對象都繼承對象的屬性和方法。任何超出鏈末端的搜索都會導致null。

在我們的示例中,x是一個從object繼承而來的空對象。x可以使用對象具有的任何屬性或方法,比如toString()。x.toString();

輸出[object Object]

這個原型鏈只有一個鏈長。x - > Object。我們知道這一點,因為如果我們試圖將兩個[[Prototype]]屬性鏈接在一起,它將為null。x.__proto__.__proto__;

輸出null

讓我們看看另一種類型的對象。如果您有使用JavaScript處理數組的經驗,就會知道它們有許多內置方法,比如pop()和push()。創建新數組時可以訪問這些方法的原因是,創建的任何數組都可以訪問array .prototype上的屬性和方法。

我們可以通過創建一個新的數組來測試它。let y = [];

請記住,我們也可以把它寫成數組構造函數,讓y = new array()。

如果我們查看新y數組的[[Prototype]],我們將看到它比x對象具有更多的屬性和方法。它繼承了Array.prototype中的所有內容。y.__proto__;[constructor: ?, concat: ?, pop: ?, push: ?, …]

您將注意到原型上的構造函數屬性被設置為Array()。構造函數屬性返回對象的構造函數,這是一種用于從函數構造對象的機制。

我們現在可以將兩個原型鏈接在一起,因為在這種情況下,我們的原型鏈更長。它看起來像y -> Array -> Object。y.__proto__.__proto__;{constructor: ?, __defineGetter__: ?, __defineSetter__: ?, …}

這個鏈現在引用Object.prototype。我們可以根據構造函數的Prototype屬性測試內部的[[Prototype]],以確定它們引用的是相同的東西。y.__proto__ === Array.prototype; // true

y.__proto__.__proto__ === Object.prototype; // true

我們還可以使用isPrototypeOf()方法來實現這一點。Array.prototype.isPrototypeOf(y); // true

Object.prototype.isPrototypeOf(Array); // true

我們可以使用instanceof操作符來測試構造函數的prototype屬性是否出現在對象原型鏈中的任何位置。y instanceof Array; // true

總而言之,所有JavaScript對象都具有隱藏的內部[[Prototype]]屬性(可能__proto__在某些瀏覽器中公開)。對象可以擴展,并將繼承[[Prototype]]其構造函數的屬性和方法。

這些原型可以被鏈接,并且每個額外的對象將繼承整個鏈中的所有內容。鏈以Object.prototype結束。

構造器函數

構造函數是用來構造新對象的函數。new操作符用于基于構造函數創建新實例。我們已經看到了一些內置的JavaScript構造函數,比如new Array()和new Date(),但是我們也可以創建自己的自定義模板來構建新對象。

例如,我們正在創建一個非常簡單的基于文本的角色扮演游戲。用戶可以選擇一個角色,然后選擇他們將擁有的角色類別,例如戰士、治療者、小偷等等。

由于每個字符將共享許多特征,例如具有名稱、級別和生命值,因此創建構造函數作為模板是有意義的。然而,由于每個角色類可能有非常不同的能力,我們希望確保每個角色只能訪問自己的能力。讓我們看看如何使用原型繼承和構造函數來實現這一點。

首先,構造函數只是一個普通函數。當使用new關鍵字的實例調用它時,它將成為一個構造函數。在JavaScript中,我們按照慣例將構造函數的第一個字母大寫。// Initialize a constructor function for a new Hero

function Hero(name, level) {

this.name = name; this.level = level;

}

我們創建了一個名為Hero的構造函數,它有兩個參數:name和level。因為每個字符都有一個名稱和一個級別,所以每個新字符都有這些屬性是有意義的。this關鍵字將引用創建的新實例,因此將this.name設置為name參數將確保新對象具有name屬性集。

現在我們可以用new創建一個新的實例。let hero1 = new Hero('Bjorn', 1);

如果我們在控制臺輸出hero1,我們將看到已經創建了一個新對象,其中新屬性按預期設置。

輸出Hero {name: "Bjorn", level: 1}

現在,如果我們得到hero1的[[Prototype]],我們將能夠看到構造函數Hero()。(記住,它的輸入與hero1相同。,但這是正確的方法。)Object.getPrototypeOf(hero1);

輸出constructor: ? Hero(name, level)

您可能注意到,我們只在構造函數中定義了屬性,而沒有定義方法。在JavaScript中,為了提高效率和代碼可讀性,通常在原型上定義方法。

我們可以使用prototype向Hero添加一個方法。我們將創建一個greet()方法。// Add greet method to the Hero prototype

Hero.prototype.greet = function () {

return `${this.name} says hello.`;

}

因為greet()在Hero的原型中,而hero1是Hero的一個實例,所以這個方法對hero1是可用的。hero1.greet();

輸出"Bjorn says hello."

如果檢查Hero的[[Prototype]],您將看到greet()現在是一個可用選項。

這很好,但是現在我們想要為英雄創建角色類。將每個類的所有功能都放到Hero構造函數中是沒有意義的,因為不同的類具有不同的功能。我們希望創建新的構造函數,但也希望它們連接到原始的Hero。

我們可以使用call()方法將屬性從一個構造函數復制到另一個構造函數。讓我們創建一個戰士和一個治療構造器。// Initialize Warrior constructor

function Warrior(name, level, weapon) {

// Chain constructor with call

Hero.call(this, name, level); // Add a new property

this.weapon = weapon;

}// Initialize Healer constructor

function Healer(name, level, spell) {

Hero.call(this, name, level); this.spell = spell;

}

兩個新的構造函數現在都具有Hero和unqiue的屬性。我們將把attack()方法添加到Warrior中,而heal()方法添加到Healer中。Warrior.prototype.attack = function () {

return `${this.name} attacks with the ${this.weapon}.`;

}

Healer.prototype.heal = function () {

return `${this.name} casts ${this.spell}.`;

}

此時,我們將使用兩個可用的新字符類創建字符。const hero1 = new Warrior('Bjorn', 1, 'axe');

const hero2 = new Healer('Kanin', 1, 'cure');

hero1現在被認為是擁有新屬性的戰士。

輸出Warrior {name: "Bjorn", level: 1, weapon: "axe"}

我們可以使用我們在戰士原型上設置的新方法。hero1.attack();Console

"Bjorn attacks with the axe."

但是如果我們嘗試使用原型鏈下面的方法會發生什么呢?hero1.greet();

輸出Uncaught TypeError: hero1.greet is not a function

使用call()鏈接構造函數時,原型屬性和方法不會自動鏈接。我們將使用Object.create()來鏈接原型,確保在創建并添加到原型的任何其他方法之前將其放置。Warrior.prototype = Object.create(Hero.prototype);

Healer.prototype = Object.create(Hero.prototype);

// All other prototype methods added below…

現在我們可以在一個戰士或治療者的實例上成功地使用Hero的原型方法。hero1.greet();

輸出"Bjorn says hello."

這里是我們的角色創建頁面的完整代碼。// Initialize constructor functions

function Hero(name, level) {

this.name = name;

this.level = level;

}

function Warrior(name, level, weapon) {

Hero.call(this, name, level);

this.weapon = weapon;

}

function Healer(name, level, spell) {

Hero.call(this, name, level);

this.spell = spell;

}

// Link prototypes and add prototype methods

Warrior.prototype = Object.create(Hero.prototype);

Healer.prototype = Object.create(Hero.prototype);

Hero.prototype.greet = function () {

return `${this.name} says hello.`;

}

Warrior.prototype.attack = function () {

return `${this.name} attacks with the ${this.weapon}.`;

}

Healer.prototype.heal = function () {

return `${this.name} casts ${this.spell}.`;

}

// Initialize individual character instances

const hero1 = new Warrior('Bjorn', 1, 'axe');

const hero2 = new Healer('Kanin', 1, 'cure');

使用這段代碼,我們已經用基本屬性創建了Hero類,從原始構造函數創建了兩個名為Warrior和Healer的字符類,向原型添加了方法,并創建了單獨的字符實例。

總結

以上是生活随笔為你收集整理的js实现html模板继承,理解JavaScript中的原型和继承的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。