ฉันเห็นคำตอบที่คล้ายกันสองสามข้อ แต่ฉันต้องการพูดถึงว่าโพสต์นี้อธิบายได้ดีที่สุดดังนั้นฉันจึงต้องการแบ่งปันกับคุณ
นี่คือโค้ดบางส่วนที่นำมาจากมันซึ่งฉันได้แก้ไขเพื่อให้ได้ตัวอย่างที่สมบูรณ์ซึ่งหวังว่าจะเป็นประโยชน์ต่อชุมชนเพราะมันสามารถใช้เป็นเทมเพลตการออกแบบสำหรับชั้นเรียนได้
นอกจากนี้ยังตอบคำถามของคุณ:
function Podcast() {
// private variables
var _somePrivateVariable = 123;
// object properties (read/write)
this.title = 'Astronomy Cast';
this.description = 'A fact-based journey through the galaxy.';
this.link = 'http://www.astronomycast.com';
// for read access to _somePrivateVariable via immutableProp
this.immutableProp = function() {
return _somePrivateVariable;
}
// object function
this.toString = function() {
return 'Title: ' + this.title;
}
};
// static property
Podcast.FILE_EXTENSION = 'mp3';
// static function
Podcast.download = function(podcast) {
console.log('Downloading ' + podcast + ' ...');
};
จากตัวอย่างนั้นคุณสามารถเข้าถึงคุณสมบัติ / ฟังก์ชั่นแบบคงที่ดังต่อไปนี้:
// access static properties/functions
console.log(Podcast.FILE_EXTENSION); // 'mp3'
Podcast.download('Astronomy cast'); // 'Downloading Astronomy cast ...'
และคุณสมบัติวัตถุ / ฟังก์ชั่นเพียงแค่เป็น:
// access object properties/functions
var podcast = new Podcast();
podcast.title = 'The Simpsons';
console.log(podcast.toString()); // Title: The Simpsons
console.log(podcast.immutableProp()); // 123
โปรดทราบว่าใน podcast.immutableProp () เรามีการปิด :การอ้างอิงถึง _somePrivateVariable จะถูกเก็บไว้ในฟังก์ชัน
คุณยังสามารถกำหนดgetters และ setters ดูตัวอย่างโค้ดนี้ (ซึ่งd
เป็นต้นแบบของวัตถุที่คุณต้องการประกาศคุณสมบัติy
เป็นตัวแปรส่วนตัวที่มองไม่เห็นนอกตัวสร้าง):
// getters and setters
var d = Date.prototype;
Object.defineProperty(d, "year", {
get: function() {return this.getFullYear() },
set: function(y) { this.setFullYear(y) }
});
มันกำหนดคุณสมบัติd.year
ผ่านget
และset
ฟังก์ชั่น - ถ้าคุณไม่ได้ระบุset
คุณสมบัตินั้นเป็นแบบอ่านอย่างเดียวและไม่สามารถแก้ไขได้ (โปรดทราบว่าคุณจะไม่ได้รับข้อผิดพลาดหากคุณพยายามตั้งค่า แต่ไม่มีผล) สถานที่ให้บริการแต่ละคนมีคุณสมบัติwritable
, configurable
(อนุญาตให้มีการเปลี่ยนแปลงหลังจากการประกาศ) และenumerable
(อนุญาตที่จะใช้เป็นตัวแจงนับ) false
ซึ่งเป็นราคาต่อค่าเริ่มต้น คุณสามารถตั้งค่าผ่านทางdefineProperty
ในพารามิเตอร์ที่ 3 enumerable: true
เช่น
สิ่งที่ถูกต้องก็คือไวยากรณ์นี้:
// getters and setters - alternative syntax
var obj = { a: 7,
get b() {return this.a + 1;},
set c(x) {this.a = x / 2}
};
ซึ่งกำหนดคุณสมบัติอ่าน / เขียนได้คุณสมบัติa
อ่านได้อย่างเดียวb
และคุณสมบัติเขียนอย่างเดียวc
ผ่านคุณสมบัติที่a
สามารถเข้าถึงได้
การใช้งาน:
console.log(obj.a); console.log(obj.b); // output: 7, 8
obj.c=40;
console.log(obj.a); console.log(obj.b); // output: 20, 21
หมายเหตุ:
เพื่อหลีกเลี่ยงพฤติกรรมที่ไม่คาดคิดในกรณีที่คุณลืมnew
คำหลักฉันแนะนำให้คุณเพิ่มสิ่งต่อไปนี้ในฟังก์ชั่นPodcast
:
// instantiation helper
function Podcast() {
if(false === (this instanceof Podcast)) {
return new Podcast();
}
// [... same as above ...]
};
ตอนนี้ทั้งสองอินสแตนซ์ต่อไปนี้จะทำงานตามที่คาดไว้:
var podcast = new Podcast(); // normal usage, still allowed
var podcast = Podcast(); // you can omit the new keyword because of the helper
คำสั่ง 'ใหม่' สร้างวัตถุใหม่และคัดลอกคุณสมบัติและวิธีการทั้งหมดเช่น
var a=new Podcast();
var b=new Podcast();
a.title="a"; b.title="An "+b.title;
console.log(a.title); // "a"
console.log(b.title); // "An Astronomy Cast"
โปรดทราบด้วยว่าในบางสถานการณ์การใช้return
คำสั่งในฟังก์ชั่น Constructor Podcast
เพื่อส่งกลับฟังก์ชั่นการปกป้องวัตถุที่กำหนดเองนั้นจะต้องอาศัยคลาสภายในซึ่งต้องมีการเปิดเผย นี่คือคำอธิบายเพิ่มเติมในบทที่ 2 (วัตถุ) ของชุดบทความ
คุณสามารถพูดได้ว่าa
และสืบทอดมาจากb
Podcast
ทีนี้จะเกิดอะไรขึ้นถ้าคุณต้องการเพิ่มวิธีการในพอดคาสต์ที่ใช้กับพวกเขาทั้งหมดหลังจากนั้นa
และb
ได้รับการเปิดตัวแล้ว? ในกรณีนี้ใช้.prototype
ดังต่อไปนี้:
Podcast.prototype.titleAndLink = function() {
return this.title + " [" + this.link + "]";
};
ตอนนี้โทรa
และb
อีกครั้ง:
console.log(a.titleAndLink()); // "a [http://www.astronomycast.com]"
console.log(b.titleAndLink()); // "An Astronomy Cast [http://www.astronomycast.com]"
คุณสามารถค้นหารายละเอียดเพิ่มเติมเกี่ยวกับต้นแบบที่นี่ หากคุณต้องการที่จะทำมรดกผมขอแนะนำให้มองเข้าไปในนี้
บทความชุดที่ผมได้กล่าวมาข้างต้นจะขอแนะนำให้อ่านพวกเขารวมถึงยังหัวข้อต่อไปนี้:
- ฟังก์ชั่น
- วัตถุ
- ต้นแบบ
- การบังคับใช้สิ่งใหม่บนฟังก์ชันตัวสร้าง
- hoisting
- การแทรกเครื่องหมายอัฒภาคอัตโนมัติ
- คุณสมบัติและวิธีการแบบคงที่
โปรดทราบว่า"คุณสมบัติ" การแทรกเครื่องหมายอัฒภาคอัตโนมัติของ JavaScript (ดังที่กล่าวไว้ใน 6) มักรับผิดชอบในการทำให้เกิดปัญหาที่แปลกในรหัสของคุณ ดังนั้นฉันค่อนข้างจะถือว่าเป็นข้อบกพร่องมากกว่าเป็นคุณสมบัติ
หากคุณต้องการอ่านเพิ่มเติมนี่เป็นบทความ MSDN ที่น่าสนใจทีเดียวเกี่ยวกับหัวข้อเหล่านี้บางหัวข้อที่อธิบายไว้มีรายละเอียดเพิ่มเติม
สิ่งที่น่าสนใจที่จะอ่านเช่นกัน (รวมถึงหัวข้อที่กล่าวถึงด้านบน) คือบทความเหล่านั้นจากคู่มือMDN JavaScript :
หากคุณต้องการทราบวิธีจำลองout
พารามิเตอร์c # (เหมือนในDateTime.TryParse(str, out result)
) ใน JavaScript คุณสามารถค้นหาโค้ดตัวอย่างได้ที่นี่
ผู้ที่ทำงานกับ IE (ซึ่งไม่มีคอนโซลสำหรับ JavaScript ยกเว้นว่าคุณเปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ที่ใช้F12และเปิดแท็บคอนโซล) อาจพบว่าข้อมูลโค้ดต่อไปนี้มีประโยชน์ อนุญาตให้คุณใช้console.log(msg);
ตามที่ใช้ในตัวอย่างด้านบน เพียงแค่ใส่ก่อนPodcast
ฟังก์ชั่น
เพื่อความสะดวกของคุณนี่คือรหัสข้างต้นในตัวอย่างโค้ดเดี่ยวที่สมบูรณ์แบบ:
let console = { log: function(msg) {
let canvas = document.getElementById("log"), br = canvas.innerHTML==="" ? "" : "<br/>";
canvas.innerHTML += (br + (msg || "").toString());
}};
console.log('For details, see the explaining text');
function Podcast() {
// with this, you can instantiate without new (see description in text)
if (false === (this instanceof Podcast)) {
return new Podcast();
}
// private variables
var _somePrivateVariable = 123;
// object properties
this.title = 'Astronomy Cast';
this.description = 'A fact-based journey through the galaxy.';
this.link = 'http://www.astronomycast.com';
this.immutableProp = function() {
return _somePrivateVariable;
}
// object function
this.toString = function() {
return 'Title: ' + this.title;
}
};
// static property
Podcast.FILE_EXTENSION = 'mp3';
// static function
Podcast.download = function(podcast) {
console.log('Downloading ' + podcast + ' ...');
};
// access static properties/functions
Podcast.FILE_EXTENSION; // 'mp3'
Podcast.download('Astronomy cast'); // 'Downloading Astronomy cast ...'
// access object properties/functions
var podcast = new Podcast();
podcast.title = 'The Simpsons';
console.log(podcast.toString()); // Title: The Simpsons
console.log(podcast.immutableProp()); // 123
// getters and setters
var d = Date.prototype;
Object.defineProperty(d, "year", {
get: function() {
return this.getFullYear()
},
set: function(y) {
this.setFullYear(y)
}
});
// getters and setters - alternative syntax
var obj = {
a: 7,
get b() {
return this.a + 1;
},
set c(x) {
this.a = x / 2
}
};
// usage:
console.log(obj.a); console.log(obj.b); // output: 7, 8
obj.c=40;
console.log(obj.a); console.log(obj.b); // output: 20, 21
var a=new Podcast();
var b=new Podcast();
a.title="a"; b.title="An "+b.title;
console.log(a.title); // "a"
console.log(b.title); // "An Astronomy Cast"
Podcast.prototype.titleAndLink = function() {
return this.title + " [" + this.link + "]";
};
console.log(a.titleAndLink()); // "a [http://www.astronomycast.com]"
console.log(b.titleAndLink()); // "An Astronomy Cast [http://www.astronomycast.com]"
<div id="log"></div>
หมายเหตุ:
เคล็ดลับที่ดีคำแนะนำและข้อเสนอแนะเกี่ยวกับการเขียนโปรแกรม JavaScript ในทั่วไปที่คุณสามารถหาได้ที่นี่ (จาวาปฏิบัติที่ดีที่สุด)และมี ( 'var' กับ 'ให้') นอกจากนี้ยังแนะนำคือบทความนี้ เกี่ยวกับ typecasts นัย (บังคับ)
วิธีที่สะดวกในการใช้คลาสและคอมไพล์ลงใน JavaScript คือTypeScript นี่คือสนามเด็กเล่นที่คุณสามารถค้นหาตัวอย่างแสดงวิธีการทำงานของมัน แม้ว่าคุณจะไม่ได้ใช้ TypeScript ในขณะนี้คุณสามารถดูได้เพราะคุณสามารถเปรียบเทียบ TypeScript กับผลลัพธ์ JavaScript ในมุมมองแบบเคียงข้างกัน ตัวอย่างส่วนใหญ่นั้นเรียบง่าย แต่ก็มีตัวอย่างของ Raytracer ที่คุณสามารถลองใช้ได้ทันที ฉันขอแนะนำให้ดูเป็นพิเศษในตัวอย่าง "การใช้คลาส", "การใช้การสืบทอด" และ "การใช้ Generics" โดยการเลือกใน Combobox ซึ่งเป็นเทมเพลตที่ดีที่คุณสามารถใช้ใน JavaScript ได้ทันที typescript จะใช้กับเชิงมุม
เพื่อให้บรรลุการห่อหุ้มของตัวแปรท้องถิ่นฟังก์ชั่นอื่น ๆ ใน JavaScript ผมแนะนำให้ใช้รูปแบบดังต่อไปนี้ (JQuery ใช้เทคนิคเดียวกัน):
<html>
<head></head>
<body><script>
'use strict';
// module pattern (self invoked function)
const myModule = (function(context) {
// to allow replacement of the function, use 'var' otherwise keep 'const'
// put variables and function with local module scope here:
var print = function(str) {
if (str !== undefined) context.document.write(str);
context.document.write("<br/><br/>");
return;
}
// ... more variables ...
// main method
var _main = function(title) {
if (title !== undefined) print(title);
print("<b>last modified: </b>" + context.document.lastModified + "<br/>");
// ... more code ...
}
// public methods
return {
Main: _main
// ... more public methods, properties ...
};
})(this);
// use module
myModule.Main("<b>Module demo</b>");
</script></body>
</html>
แน่นอนคุณสามารถ - และควร - ใส่รหัสสคริปต์ใน*.js
ไฟล์แยกต่างหาก นี่เป็นเพียงการเขียนแบบอินไลน์เพื่อให้ตัวอย่างสั้น
ฟังก์ชั่นตัวเอง invocing (ยังเป็นที่รู้จักในฐานะ IIFE = Expression ฟังก์ชั่นเรียกทันที) จะอธิบายในรายละเอียดเพิ่มเติมได้ที่นี่