ฉันเริ่มสับสนว่าควรจะสร้างวัตถุในจาวาสคริปต์ด้วยวิธีใด ดูเหมือนว่ามีอย่างน้อยสองวิธี หนึ่งคือการใช้สัญกรณ์ตามตัวอักษรของวัตถุในขณะที่อีกอันใช้ฟังก์ชันการก่อสร้าง มีข้อได้เปรียบเหนือข้ออื่น ๆ หรือไม่?
ฉันเริ่มสับสนว่าควรจะสร้างวัตถุในจาวาสคริปต์ด้วยวิธีใด ดูเหมือนว่ามีอย่างน้อยสองวิธี หนึ่งคือการใช้สัญกรณ์ตามตัวอักษรของวัตถุในขณะที่อีกอันใช้ฟังก์ชันการก่อสร้าง มีข้อได้เปรียบเหนือข้ออื่น ๆ หรือไม่?
คำตอบ:
หากคุณไม่มีพฤติกรรมที่เกี่ยวข้องกับอ็อบเจ็กต์ (กล่าวคือถ้าอ็อบเจ็กต์เป็นเพียงคอนเทนเนอร์สำหรับข้อมูล / สถานะ) ฉันจะใช้อ็อบเจกต์ลิเทอรัล
var data = {
foo: 42,
bar: 43
};
ใช้หลักการ KISS หากคุณไม่ต้องการอะไรเลยนอกจากที่เก็บข้อมูลแบบธรรมดาให้ไปใช้ตัวอักษรธรรมดา ๆ
หากคุณต้องการเพิ่มลักษณะการทำงานให้กับวัตถุของคุณคุณสามารถใช้ตัวสร้างและเพิ่มวิธีการให้กับวัตถุในระหว่างการสร้างหรือให้ชั้นเรียนของคุณเป็นต้นแบบ
function MyData(foo, bar) {
this.foo = foo;
this.bar = bar;
this.verify = function () {
return this.foo === this.bar;
};
}
// or:
MyData.prototype.verify = function () {
return this.foo === this.bar;
};
คลาสเช่นนี้ยังทำหน้าที่เหมือนสคีมาสำหรับอ็อบเจ็กต์ข้อมูลของคุณ: ขณะนี้คุณมีสัญญาบางประเภท (ผ่านตัวสร้าง) คุณสมบัติที่อ็อบเจ็กต์เริ่มต้น / มี ลิเทอรัลฟรีเป็นเพียงแค่ข้อมูลที่ไม่มีรูปร่าง
คุณอาจมีverifyฟังก์ชันภายนอกที่ทำหน้าที่กับอ็อบเจ็กต์ข้อมูลเก่าธรรมดา:
var data = {
foo: 42,
bar: 43
};
function verify(data) {
return data.foo === data.bar;
}
อย่างไรก็ตามสิ่งนี้ไม่เอื้ออำนวยต่อการห่อหุ้ม: ตามหลักการแล้วข้อมูล + พฤติกรรมทั้งหมดที่เกี่ยวข้องกับเอนทิตีควรอยู่ร่วมกัน
this.fn = function ...วิธีการในตัวสร้างอินสแตนซ์อ็อบเจ็กต์แต่ละรายการของคุณจะมีสำเนาฟังก์ชัน เมื่อใช้แนวทางต้นแบบคุณจะแนบแต่ละฟังก์ชันเพียงครั้งเดียว: ฟังก์ชันเหล่านี้จะถูกสืบทอดโดยอินสแตนซ์ผ่านการสืบทอดต้นแบบ
โดยพื้นฐานแล้วมันจะเดือดขึ้นถ้าคุณต้องการหลายอินสแตนซ์ของวัตถุของคุณหรือไม่ วัตถุที่กำหนดด้วยตัวสร้างช่วยให้คุณมีหลายอินสแตนซ์ของออบเจ็กต์นั้น โดยพื้นฐานแล้ว Object literals นั้นมีตัวแปร / วิธีการที่เป็นแบบสาธารณะทั้งหมด
// define the objects:
var objLit = {
x: 0,
y: 0,
z: 0,
add: function () {
return this.x + this.y + this.z;
}
};
var ObjCon = function(_x, _y, _z) {
var x = _x; // private
var y = _y; // private
this.z = _z; // public
this.add = function () {
return x + y + this.z; // note x, y doesn't need this.
};
};
// use the objects:
objLit.x = 3;
objLit.y = 2;
objLit.z = 1;
console.log(objLit.add());
var objConIntance = new ObjCon(5,4,3); // instantiate an objCon
console.log(objConIntance.add());
console.log((new ObjCon(7,8,9)).add()); // another instance of objCon
console.log(objConIntance.add()); // same result, not affected by previous line
อีกวิธีหนึ่งในการสร้างวัตถุในลักษณะเดียวกันคือการใช้ฟังก์ชันที่ส่งคืนวัตถุ:
function makeObject() {
var that = {
thisIsPublic: "a public variable"
thisIsAlsoPublic: function () {
alert(that.thisIsPublic);
}
};
var secret = "this is a private variable"
function secretFunction() { // private method
secret += "!"; // can manipulate private variables
that.thisIsPublic = "foo";
}
that.publicMethod = function () {
secret += "?"; // this method can also mess with private variables
}
that.anotherPublicVariable = "baz";
return that; // this is the object we've constructed
}
makeObject.static = "This can be used to add a static varaible/method";
var bar = makeObject();
bar.publicMethod(); // ok
alert(bar.thisIsPublic); // ok
bar.secretFunction(); // error!
bar.secret // error!
เนื่องจากฟังก์ชันใน JavaScript เป็นการปิดเราจึงสามารถใช้ตัวแปรและวิธีการส่วนตัวและหลีกเลี่ยงnewได้
จากhttp://javascript.crockford.com/private.htmlเกี่ยวกับตัวแปรส่วนตัวใน JavaScript
โค้ดด้านล่างนี้แสดงให้เห็นว่าสามวิธีในการสร้างวัตถุวัตถุไวยากรณ์ตัวอักษร, Object.create()ฟังก์ชั่นและสร้าง วากยสัมพันธ์ของ Object Literal นั้นสร้างและสร้างวัตถุได้ทันทีและด้วยเหตุ__prototype__นี้จึงเป็นObjectวัตถุและจะสามารถเข้าถึงคุณสมบัติและวิธีการทั้งหมดของObjectวัตถุและมันจะมีการเข้าถึงคุณสมบัติและวิธีการของจากมุมมองรูปแบบการออกแบบอย่างเคร่งครัดควรใช้ Object literal อย่างง่ายเพื่อจัดเก็บข้อมูลอินสแตนซ์เดียว
.prototypeตัวสร้างฟังก์ชั่นได้คุณสมบัติพิเศษชื่อ คุณสมบัตินี้จะกลายเป็น__prototype__ของอ็อบเจ็กต์ใด ๆ ที่สร้างโดยตัวสร้างฟังก์ชัน คุณสมบัติและวิธีการทั้งหมดที่เพิ่มลงใน.prototypeคุณสมบัติของตัวสร้างฟังก์ชันจะพร้อมใช้งานสำหรับอ็อบเจ็กต์ทั้งหมดที่สร้างขึ้น ควรใช้ตัวสร้างหากคุณต้องการข้อมูลหลายอินสแตนซ์หรือต้องการพฤติกรรมจากออบเจ็กต์ของคุณ โปรดทราบว่าตัวสร้างฟังก์ชันยังใช้ได้ดีที่สุดเมื่อคุณต้องการจำลองรูปแบบการพัฒนาส่วนตัว / สาธารณะ อย่าลืมใส่เมธอดที่ใช้ร่วมกันทั้งหมด.prototypeเพื่อที่จะไม่ถูกสร้างขึ้นในแต่ละอินสแตนซ์ออบเจ็กต์
การสร้างอ็อบเจกต์โดยObject.create()ใช้อ็อบเจกต์ลิเทอรัลเป็น__prototype__อ็อบเจกต์ที่สร้างโดยวิธีนี้ คุณสมบัติและวิธีการทั้งหมดที่เพิ่มลงในตัวอักษรของอ็อบเจ็กต์จะพร้อมใช้งานสำหรับอ็อบเจ็กต์ทั้งหมดที่สร้างขึ้นจากการสืบทอดโปรโตไทป์ที่แท้จริง นี่เป็นวิธีที่ฉันชอบ
//Object Example
//Simple Object Literal
var mySimpleObj = {
prop1 : "value",
prop2 : "value"
}
// Function Constructor
function PersonObjConstr() {
var privateProp = "this is private";
this.firstname = "John";
this.lastname = "Doe";
}
PersonObjConstr.prototype.greetFullName = function() {
return "PersonObjConstr says: Hello " + this.firstname +
" " + this.lastname;
};
// Object Literal
var personObjLit = {
firstname : "John",
lastname: "Doe",
greetFullName : function() {
return "personObjLit says: Hello " + this.firstname +
", " + this.lastname;
}
}
var newVar = mySimpleObj.prop1;
var newName = new PersonObjConstr();
var newName2 = Object.create(personObjLit);
Object.createฟังก์ชันภายในลิเทอรัลจะไม่ซ้ำกันต่ออินสแตนซ์หรือไม่?
ขึ้นอยู่กับว่าคุณต้องการทำอะไร หากคุณต้องการใช้ตัวแปรส่วนตัว (กึ่ง) หรือฟังก์ชันในอ็อบเจ็กต์ของคุณฟังก์ชันคอนสตรัคเตอร์เป็นวิธีที่จะทำ หากอ็อบเจ็กต์ของคุณมีเฉพาะคุณสมบัติและวิธีการเท่านั้นอ็อบเจ็กต์ลิเทอรัลก็ใช้ได้
function SomeConstructor(){
var x = 5;
this.multiply5 = function(i){
return x*i;
}
}
var myObj = new SomeConstructor;
var SomeLiteral = {
multiply5: function(i){ return i*5; }
}
ตอนนี้วิธีการmultiply5ในmyObjและSomeLiteralทำสิ่งเดียวกัน ข้อแตกต่างเพียงอย่างเดียวคือ myObj ใช้ตัวแปรส่วนตัว อย่างหลังอาจมีประโยชน์ในบางกรณี บ่อยครั้งที่ Object literal เพียงพอและเป็นวิธีที่ดีและสะอาดในการสร้าง JS-object
คุณต้องการอินสแตนซ์เดียวของออบเจ็กต์สำหรับเพจ - Literal
คุณต้องการเพียงแค่ถ่ายโอนข้อมูลเช่น DTO ออบเจ็กต์ง่ายๆ GET SET: - Literal
คุณต้องการสร้างวัตถุจริงด้วยลักษณะการทำงานของวิธีการหลายอินสแตนซ์ - ฟังก์ชันตัวสร้างปฏิบัติตามหลักการ OOP การสืบทอด: - ฟังก์ชันตัวสร้าง
ด้านล่างนี้คือวิดีโอ youtube ซึ่งอธิบายรายละเอียดว่าอะไรคือตัวอักษรฟังก์ชันตัวสร้างคืออะไรและแตกต่างกันอย่างไร
ไปกับ object literal มันกระชับมากขึ้นและขยายได้ดีขึ้นด้วยการแนะนำค่าเริ่มต้น
ตามที่กล่าวไว้ในhttps://www.w3schools.com/js/js_object_definition.asp
การใช้ตัวอักษรวัตถุที่คุณทั้งสองกำหนดและสร้าง , หนึ่งวัตถุในหนึ่ง คำสั่ง
นอกจากนี้
Object literal จะสร้างวัตถุเดียวเท่านั้น บางครั้งเราชอบที่จะมีประเภทวัตถุที่สามารถใช้สร้างวัตถุประเภทเดียวได้หลายชิ้น
ฟังก์ชันตัวสร้าง Object () ช้าลงเล็กน้อยและมีรายละเอียดมากกว่า ด้วยเหตุนี้วิธีที่แนะนำในการสร้างวัตถุใหม่ใน JavaScript คือการใช้สัญกรณ์ตามตัวอักษร
ที่จริงแล้ว methinks เราสามารถมีเมธอดส่วนตัวในอ็อบเจกต์ลิเทอรัล พิจารณาโค้ดด้านล่าง:
var myObject = {
publicMethod: function () {
privateMethod1();
privateMethod2();
function privateMethod1(){
console.log('i am privateMethod1');
}
function privateMethod2(){
console.log('i am privateMethod2');
}
}
}
เรื่องของรสนิยม แต่ฉันชอบที่จะใช้ตัวอักษรที่เป็นไปได้
// ตัวสร้าง Object Literal และ Object
function MyData(foo, bar) {
this.foo = foo;
this.bar = bar;
}
MyData.prototype.verify = function () {
return this.foo === this.bar;
};
//add property using prototype
var MD = new MyData;//true.
var MD = new MyData();//true.
MD.verify// return only the function structure.
MD.verify(); //return the verify value and in this case return true coz both value is null.
var MD1 = new MyData(1,2); // intialized the value at the starting.
MD1.verify// return only the function structure.
MD1.verify(); // return false coz both value are not same.
MD1.verify(3,3);// return false coz this will not check this value intialized at the top
MyData.prototype.verify = function (foo,bar) {
return this.foo === this.bar;
};
var MD1 = new MyData(1,2);
MD1.verify();
MD1.verify(3,3);// return false coz this keyword used with foo and bar that will check parent data