ฉันค่อนข้างใหม่กับ JavaScript และยังคงเห็น .extend และ .prototype ในไลบรารีของบุคคลที่สามที่ฉันใช้อยู่ ฉันคิดว่ามันเกี่ยวข้องกับไลบรารี Prototype javascript แต่ฉันเริ่มคิดว่ามันไม่ใช่อย่างนั้น สิ่งเหล่านี้ใช้ทำอะไร?
ฉันค่อนข้างใหม่กับ JavaScript และยังคงเห็น .extend และ .prototype ในไลบรารีของบุคคลที่สามที่ฉันใช้อยู่ ฉันคิดว่ามันเกี่ยวข้องกับไลบรารี Prototype javascript แต่ฉันเริ่มคิดว่ามันไม่ใช่อย่างนั้น สิ่งเหล่านี้ใช้ทำอะไร?
คำตอบ:
การสืบทอดของ Javascript นั้นขึ้นอยู่กับต้นแบบดังนั้นคุณจึงขยายต้นแบบของวัตถุเช่นวันที่คณิตศาสตร์และแม้แต่วัตถุที่คุณกำหนดเอง
Date.prototype.lol = function() {
alert('hi');
};
( new Date ).lol() // alert message
ในตัวอย่างด้านบนฉันกำหนดวิธีการสำหรับอ็อบเจ็กต์ Date ทั้งหมด (อ็อบเจ็กต์ที่มีอยู่แล้วและอ็อบเจ็กต์ใหม่ทั้งหมด)
extend
โดยปกติจะเป็นฟังก์ชันระดับสูงที่คัดลอกต้นแบบของคลาสย่อยใหม่ที่คุณต้องการขยายจากคลาสพื้นฐาน
ดังนั้นคุณสามารถทำสิ่งต่างๆเช่น:
extend( Fighter, Human )
และคอนFighter
สตรัคเตอร์ / อ็อบเจกต์จะสืบทอดต้นแบบของHuman
ดังนั้นหากคุณกำหนดวิธีการเช่นlive
และdie
ต่อไปHuman
ก็Fighter
จะสืบทอดสิ่งเหล่านั้นด้วย
อัปเดตคำชี้แจง:
"ฟังก์ชันระดับสูง" ความหมาย .extend ไม่ได้อยู่ในตัว แต่มักจัดเตรียมโดยไลบรารีเช่น jQuery หรือ Prototype
changing the native objects can break other developer's assumptions of these objects,
นำไปสู่จุดบกพร่องของจาวาสคริปต์ซึ่งมักใช้เวลาหลายชั่วโมงในการติดตาม ดูเหมือนว่าประโยคนำหน้าคำตอบนี้จะบิดเบือนความจริงในการฝึกจาวาสคริปต์ที่มีคุณค่านี้
.extend()
ถูกเพิ่มโดยไลบรารีของบุคคลที่สามจำนวนมากเพื่อให้ง่ายต่อการสร้างวัตถุจากวัตถุอื่น ๆ ดูhttp://api.jquery.com/jQuery.extend/หรือhttp://www.prototypejs.org/api/object/extendสำหรับตัวอย่างบางส่วน
.prototype
หมายถึง "แม่แบบ" (ถ้าคุณต้องการเรียกมันว่า) ของวัตถุดังนั้นโดยการเพิ่มวิธีการลงในต้นแบบของวัตถุ (คุณเห็นสิ่งนี้มากในไลบรารีเพื่อเพิ่มใน String, Date, Math หรือแม้แต่ Function) วิธีการเหล่านั้น จะถูกเพิ่มลงในอินสแตนซ์ใหม่ทุกชิ้นของออบเจ็กต์นั้น
extend
วิธีการเช่นในjQueryหรือPrototypeJSสำเนาคุณสมบัติทั้งหมดจากแหล่งไปยังวัตถุที่ปลายทาง
ตอนนี้เกี่ยวกับprototype
คุณสมบัติเป็นสมาชิกของวัตถุฟังก์ชันซึ่งเป็นส่วนหนึ่งของแกนภาษา
สามารถใช้ฟังก์ชันใด ๆ เป็นตัวสร้างเพื่อสร้างอินสแตนซ์ออบเจ็กต์ใหม่ได้ ฟังก์ชันทั้งหมดมีprototype
คุณสมบัตินี้
เมื่อคุณใช้new
โอเปอเรเตอร์กับอ็อบเจ็กต์ฟังก์ชันอ็อบเจ็กต์ใหม่จะถูกสร้างขึ้นและจะสืบทอดจากคอนสตรัคprototype
เตอร์
ตัวอย่างเช่น:
function Foo () {
}
Foo.prototype.bar = true;
var foo = new Foo();
foo.bar; // true
foo instanceof Foo; // true
Foo.prototype.isPrototypeOf(foo); // true
การสืบทอด Javascript ดูเหมือนจะเป็นการอภิปรายที่เปิดกว้างในทุกๆที่ เรียกได้ว่าเป็น "กรณีที่น่าสงสัยของภาษา Javascript"
แนวคิดคือมีคลาสพื้นฐานแล้วคุณขยายคลาสฐานเพื่อให้ได้คุณสมบัติที่เหมือนการสืบทอด (ไม่สมบูรณ์ แต่ยังคงอยู่)
แนวคิดทั้งหมดคือการได้รับสิ่งที่ต้นแบบมีความหมายจริงๆ ฉันไม่ได้รับมันจนกว่าฉันจะเห็นรหัสของ John Resig (ใกล้เคียงกับสิ่งที่jQuery.extend
ทำ) เขียนโค้ดที่ทำและเขาอ้างว่า base2 และไลบรารีต้นแบบเป็นแหล่งที่มาของแรงบันดาลใจ
นี่คือรหัส
/* Simple JavaScript Inheritance
* By John Resig http://ejohn.org/
* MIT Licensed.
*/
// Inspired by base2 and Prototype
(function(){
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
// The base Class implementation (does nothing)
this.Class = function(){};
// Create a new Class that inherits from this class
Class.extend = function(prop) {
var _super = this.prototype;
// Instantiate a base class (but only create the instance,
// don't run the init constructor)
initializing = true;
var prototype = new this();
initializing = false;
// Copy the properties over onto the new prototype
for (var name in prop) {
// Check if we're overwriting an existing function
prototype[name] = typeof prop[name] == "function" &&
typeof _super[name] == "function" && fnTest.test(prop[name]) ?
(function(name, fn){
return function() {
var tmp = this._super;
// Add a new ._super() method that is the same method
// but on the super-class
this._super = _super[name];
// The method only need to be bound temporarily, so we
// remove it when we're done executing
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, prop[name]) :
prop[name];
}
// The dummy class constructor
function Class() {
// All construction is actually done in the init method
if ( !initializing && this.init )
this.init.apply(this, arguments);
}
// Populate our constructed prototype object
Class.prototype = prototype;
// Enforce the constructor to be what we expect
Class.prototype.constructor = Class;
// And make this class extendable
Class.extend = arguments.callee;
return Class;
};
})();
มีสามส่วนที่กำลังทำงานอยู่ ขั้นแรกคุณวนซ้ำคุณสมบัติและเพิ่มลงในอินสแตนซ์ หลังจากนั้นคุณสร้างตัวสร้างเพื่อเพิ่มเข้าไปในวัตถุในภายหลังตอนนี้บรรทัดสำคัญคือ:
// Populate our constructed prototype object
Class.prototype = prototype;
// Enforce the constructor to be what we expect
Class.prototype.constructor = Class;
ก่อนอื่นให้ชี้Class.prototype
ไปที่ต้นแบบที่ต้องการ ตอนนี้วัตถุทั้งหมดเปลี่ยนไปหมายความว่าคุณต้องบังคับให้เค้าโครงกลับไปเป็นของตัวเอง
และตัวอย่างการใช้งาน:
var Car = Class.Extend({
setColor: function(clr){
color = clr;
}
});
var volvo = Car.Extend({
getColor: function () {
return color;
}
});
อ่านเพิ่มเติมได้ที่นี่ที่Javascript Inheritance by John Resig 's post
extend
ฟังก์ชันบางอย่างในไลบรารีของบุคคลที่สามซับซ้อนกว่าฟังก์ชันอื่น ๆ ตัวอย่างเช่นKnockout.jsมีสิ่งที่เรียบง่ายน้อยที่สุดที่ไม่มีการตรวจสอบบางอย่างที่ jQuery ทำ:
function extend(target, source) {
if (source) {
for(var prop in source) {
if(source.hasOwnProperty(prop)) {
target[prop] = source[prop];
}
}
}
return target;
}
.extends()
สร้างคลาสซึ่งเป็นลูกของคลาสอื่น Child.prototype.__proto__
กำหนดคุณค่าของมันเพื่อParent.prototype
.prototype
สืบทอดคุณสมบัติจากคนหนึ่งไปยังอีกคนหนึ่ง.__proto__
เป็น getter / setter สำหรับ Prototype
.extend
ไม่ได้อยู่ในตัว แต่มักจัดเตรียมโดยไลบรารีเช่น jQuery หรือ Prototype