您需要了解的是Prototype
的概念。
當您使用new
創建實例時,您正在構建基於原型的對象。
考慮以下幾點:
function Person(name) {
this.name = name;
this.speak = function (msg) {
console.log('Person says:' + msg);
};
}
var dad = new Person('David');
dad.speak('I am your dad!');
console.log('Is dad.speak equal to dad.speak?', dad.speak === dad.speak);
var mom = new Person('David');
console.log('Is mom.speak equal to dad.speak?', mom.speak === dad.speak);
每次構建的Person
一個新實例,新speak
原型現在周圍漂浮在某處你的邏輯。這是非常低效的。
爲了解決這個問題,我們需要修改我們的函數的prototype
:
function Person(name) {
this.name = name;
}
Person.prototype.speak = function (msg) {
console.log('Person says:' + msg);
};
var dad = new Person('David');
dad.speak('I am your dad!');
console.log('Is dad.speak equal to dad.speak?', dad.speak === dad.speak);
var mom = new Person('David');
console.log('Is mom.speak equal to dad.speak?', dad.speak === dad.speak);
這樣,我們只需要創建一次函數,其上繼承到所有prototype
實例。這更容易維護,效率更高。
現在我們可以通過他們prototype
擴展DOM對象,但不建議這樣做,因爲你開始與web標準的混亂,使故障排除變得更加困難。
Array.prototype.isLengthGreaterThanFive = function(thisArg) {
return this.length > 5;
};
console.log([1, 2, 3, 4].isLengthGreaterThanFive(), [1, 2, 3, 4, 5, 6].isLengthGreaterThanFive());
處理這更好的方法是創建一個擴展的對象,或者簡單地使用功能:
//Using functions
function isLengthGreaterThanFive(array) {
return array.length > 5;
}
console.log(isLengthGreaterThanFive([1, 2, 3, 4]), isLengthGreaterThanFive([1, 2, 3, 4, 5, 6]));
//Using a wrapper class
var MyArray = (function() {
function MyArray(array) {
if (array === void 0) {
array = [];
}
this.array = array;
}
MyArray.prototype.isLengthGreaterThanFive = function() {
return this.array.length > 5;
};
return MyArray;
}());
console.log(new MyArray([1, 2, 3, 4]).isLengthGreaterThanFive(), new MyArray([1, 2, 3, 4, 5, 6]).isLengthGreaterThanFive());
使用類的好處是,我們可以在我們的對象的理念延伸:
//Base class
function Person(firstname, lastname, says) {
if (firstname === void 0) {
firstname = "Leonado";
}
this.firstname = firstname;
if (lastname === void 0) {
lastname = "Da Vinci";
}
this.lastname = lastname;
if (says === void 0) {
says = "hello";
}
this.says = says;
}
//Base methods
Person.prototype.iAm = function() {
return this.firstname + " " + this.lastname;
};
Person.prototype.Speak = function() {
return this.says + " my name is " + this.iAm();
};
//Extended class
function Warrior(firstname, lastname, says) {
//Call in constructor
Person.call(this, firstname, lastname, says);
}
//Inheriting
Warrior.prototype = Object.create(Person.prototype);
Warrior.prototype.constructor = Warrior;
//Overruling "Speak"
Warrior.prototype.Speak = function() {
return "My name is " + this.iAm() + ", " + this.says;
};
console.log([new Warrior("Peter", "Allan", "Ahoyhoy").Speak(), new Person("Peter", "Allan", "Ahoyhoy").Speak()]);
在上面的例子中,我們爲Warrior
因此延長Person
原型我們保留Person
的功能,然後簡單地修改Warrior
的不同之處。這樣我們可以重新使用原型方法iAm
,我們可以專注於僅改變Speak
方法中需要更改的內容。
編輯1
我發現爲時已晚,該問題已經改變了一點。
你可以把DOM元素,如JavaScript中的任何其他類。以下安裝有所有Persons
共享單個DIV
到speakUp
:
var Person = (function() {
function Person(age, firstname, lastname) {
if (age === void 0) { age = 50; }
if (firstname === void 0) { firstname = "Peter"; }
if (lastname === void 0) { lastname = "Venkman"; }
this.age = age;
this.firstname = firstname;
this.lastname = lastname;
}
Person.prototype.speakUp = function() {
Person.bubble.innerHTML = this.firstname + " " + this.lastname + " is " + this.age + " years old";
};
return Person;
}());
Person.bubble = document.createElement("div");
document.body.appendChild(Person.bubble);
setInterval(function() {
var p = new Person(Math.floor(Math.random() * 100));
p.speakUp();
}, 3000);
這很容易成爲DIV
每Person
,或所有Person
選自S共享一個refereced DOM對象(的document.getElementById) 。
EDIT 2
在回答您的評論:
在JavaScript中的一切在本質上和object
。你創建一個函數,它用函數名稱object
註冊並返回object
和instance
。像Arrays
,Strings
,DOM
等元素和自定義功能都有一些object
隱藏在幕後。每創建一個新的Array
或DOM
元素或其他東西,它都會引用其主對象(稱爲原型)。這被稱爲原型鏈。
如果你看看我的第二個例子,當dad.speak
被稱爲JavaScript的第一個搜索實例爲speak
屬性,但它不會找到一個,因爲我們還沒有分配它,我們做的方式例如在一個是它是特定於實例的。
然後JavaScript會嘗試一個級別上的prototype
鏈,在這裏它會找到一個匹配的屬性,並用它來代替。通過這種方式,我們可以改變JavaScript中現有元素的自定義或的默認行爲。
這個想法是,如果你有一些屬性,原型的所有實例應該有,那麼我們只需修改一次原型,他們將全部inherit
這個屬性。
想想這樣。如果你用JavaScript描述地球上的所有生物,你會想要某種形式的分組。例如,第一個級別就像是一個Exists
對象,它攜帶一個名稱和一個id的屬性。從這裏你可以創建Plant
和Animal
並讓它們都繼承Exists
的原型。現在我們可以創建一個繼承Plant
的Flower
類和繼承Flower
等的Rose
類。
這個想法是以一種對人類有意義的方式通過繼承來應用你的屬性(一隻貓頭鷹可以飛,因爲它是一隻鳥/一隻鯊魚可以游泳,因爲它是一條魚)。將它們綁定在有意義的級別上,以邏輯模式繼承並有效利用您的時間。
如果您仍然感到困惑,請嘗試查找prototype
教程。
這裏是一個很好的Youtube視頻來解釋它:
https://www.youtube.com/watch?v=PMfcsYzj-9M
嘗試MDN的解釋考慮看看:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain –
你有Person對象的兩個參數,因此它會是'var dad = new Person($('#dad'),'David');'then'dad.speak('我是你的爸爸!');' –
@ oliv37哎呀,糾正它;) –