Я заплутався у тому, яким чином слід створювати об’єкт у javascript. Здається, існує як мінімум два способи. Один - використовувати буквальні нотації об’єкта, тоді як інший використовує конструктивні функції. Чи є перевага одного над іншим?
Я заплутався у тому, яким чином слід створювати об’єкт у javascript. Здається, існує як мінімум два способи. Один - використовувати буквальні нотації об’єкта, тоді як інший використовує конструктивні функції. Чи є перевага одного над іншим?
Відповіді:
Якщо у вас немає поведінки, пов'язаної з об'єктом (тобто, якщо об'єкт - це просто контейнер для даних / стану), я б використав літерал об'єкта.
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 ...застосуєте підхід у конструкторі, кожен екземпляр об’єкта матиме власні копії функцій. Використовуючи підхід прототипу, ви приєднуєте кожну функцію один раз і лише один раз: вони успадковуватимуться екземплярами через прототипне успадкування.
По суті, це зводиться до того, потрібні вам численні екземпляри вашого об’єкта чи ні; об'єкт, визначений конструктором, дозволяє мати кілька екземплярів цього об'єкта. Об’єктивні літерали - це в основному одиночні елементи зі змінними / методами, які є загальнодоступними.
// 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(). Об'єктний буквальний синтаксис просто створює та об'єктує на льоту і як такий __prototype__є Objectоб'єктом, і він матиме доступ до всіх властивостей та методівObject . Суворо з точки зору дизайну, для зберігання єдиного екземпляра даних слід використовувати простий літеральний об’єкт.
Конструктор функцій має спеціальну властивість з назвою .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 використовує приватну змінну. Останні можуть бути корисними в деяких випадках. У більшості випадків літералу Об’єкту є достатнім і приємним і чистим способом створення JS-об’єкта.
Хочете одиничний екземпляр об’єкта для сторінки - буквальний.
Ви хочете просто передавати дані, такі як об'єкти DTO, просто GET SET: - Буквальний
Ви хочете створити реальні об'єкти з поведінкою методів, декількома екземплярами - функція конструктора, дотримуйтесь принципів ООП, успадкування: - функції конструктора.
Нижче наведено відео з YouTube, яке докладно пояснює, що таке літерал, що таке функції конструктора та чим вони відрізняються одна від одної.
Перейдіть з об'єктом буквально, він стає меншим і краще розширюється із введенням початкових значень.
Як згадано в https://www.w3schools.com/js/js_object_definition.asp
З допомогою литерала об'єкта, ви обидва визначити і створити , один об'єкт в одному заяві.
Також
Об'єкт буквально створює лише один об'єкт. Іноді нам подобається мати об’єктний тип, який можна використовувати для створення багатьох об’єктів одного типу.
Функція конструктора Object () трохи повільніша і багатослівніша. Таким чином, рекомендованим способом створення нових об’єктів у JavaScript є використання буквальних позначень
Насправді, міркуючи, ми можемо мати приватні методи в об'єктних літералах. Розглянемо код нижче:
var myObject = {
publicMethod: function () {
privateMethod1();
privateMethod2();
function privateMethod1(){
console.log('i am privateMethod1');
}
function privateMethod2(){
console.log('i am privateMethod2');
}
}
}
Питання смаку, але я вважаю за краще використовувати об'єктивні літерали там, де це можливо.
// Об’єктний літерал та конструктор об’єктів
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