Подтвердить что ты не робот

Создание объектов Javascript - несколько подходов, любые различия?

Я видел несколько разных способов создания объектов в javascript, хотел узнать преимущества/недостатки различных подходов и почему вы использовали бы один из них.

Подход 1

var obj = {
    prop: value,
    .
    .
    .
}

Подход один - стандартный подход, ничего нового:)

Подход 2

var obj = new function() {
    var prop1 = value1;
    var fn1 = function() {
    };
    .
    .
    .

    this.prop2 = value2;
    .
    .
    .
}();

Функциональный подход, я хотел сравнить этот подход с подходом 3. Функциональный подход в основном используется для инкапсуляции (правильно?)

Подход 3

var obj = (function() {
    var prop1 = value1;
    var fn1 = function() {
    };
    .
    .
    .

    return {
        prop2: value2,
        .
        .
        .
    }
})();

При таком подходе я не совсем понимаю причины его использования. Как он отличается от подхода 2? Оба могут использоваться для инкапсуляции логики.

Это значит, что мы можем передавать параметры, поэтому мы можем иметь дело с любыми потенциальными конфликтами? Например, синтаксис jquery $, но вы также можете сделать это с помощью подхода 2...

Спасибо.


Edit:


Я знаю, что подход 1 и 3 схожи (в том, что они оба возвращают объекты), однако подход 3 также создает замыкание. Какой подход 2 также делает.

Это основа моего вопроса, и как 2, так и 3 создают замыкания, но в чем разница между ними.

4b9b3361

Ответ 1

В подходе # 2 и # 3 свойство constructor результирующих объектов будет отличаться.

На практике это означает, что второй подход позволяет вам создавать несколько объектов с помощью функции анонимного конструктора:

x = new function() { alert(1) };
y = new x.constructor; // shows the message too

Верхний ответ Образец модуля против экземпляра анонимного конструктора включает цитату из Дугласа Крокфорда, в которой он объясняет, почему он считает, что подход №3 лучше, чем # 2.

Ответ 2

7 способов создания объектов в JavaScript:

1. Конструктор объектов

Самый простой способ создать объект - использовать конструктор Object: просмотреть прозрачность?

var person = new Object();  
person.name = "Diego";  
person.getName = function(){  
    return this.name;  
}; 

2. Буквенная нотация

просмотреть plainprint?

var person = {  
    person.name : "Diego",  
    person.getName : function(){  
        return this.name;  
    }  
} 

3. Factory функция

Функция Factory позволяет инкапсулировать и повторно использовать логику для создания похожих объектов. Для этого он использует любую из предыдущих конструкций. Или: просмотреть прозрачность?

var newPerson=function(name){  
    var result = new Object();  
    result.name = name;  
    result.getName = function(){  
        return this.name;  
    };  
    return result;  
};  
var personOne = newPerson("Diego");  
var personTwo = newPerson("Gangelo");  
console.log(personOne.getName()); // prints Diego  
console.log(personTwo.getName()); // prints Gangelo

Или:

view plainprint?
var newPerson=function(name){  
    return {  
        person.name : name,  
        person.getName : function(){  
            return this.name;  
        };  
};  
var personOne = newPerson("Diego");  
var personTwo = newPerson("Gangelo");  
console.log(personOne.getName()); // prints Diego  
console.log(personTwo.getName()); // prints Gangelo  

4. Конструктор функций

В Javascript можно вызвать любую функцию с новым оператором перед ним. Для функции F для новых F(): создается новый пустой объект X. X задается как контекст для F, означающий всюду по F, это указывает на X. X возвращается в результате F просмотреть прозрачность?

function Person(name){  
        this.name = name;  
        this.getName = function(){  
            return this.name;  
        };  
};  
var personOne = new Person("Diego");  
console.log(personOne.getName()); // prints Diego  
console.log(personOne instanceOf Person); // prints true  
console.log(personOne.constructor === Person); // prints true  
console.log(personOne instanceOf Object); // prints true  

5. Прототип

Функции очень специфичны в Javascript. Это объекты, они могут создавать другие объекты, и они автоматически получают поле, называемое прототипом. Прототип - это простой объект с одним полем, называемым конструктором, указывающим на саму функцию. Особенность заключается в том, что каждый объект, созданный через функцию, наследует прототип функции. просмотреть прозрачность?

function Person(){};  
Person.prototype.name = "Diego";  
var personOne = new Person();  
var personTwo = new Person();  
console.log(personOne.constructor == Person); // prints true  
console.log(personOne.name); // prints Diego  
console.log(personTwo.constructor == Person); // prints true  
console.log(personTwo.name); // prints Diego  

6. Комбинация функций/прототипов

Комбинация функций/прототипов, как вы могли бы себе представить, использует оба подхода:) просмотреть прозрачность?

function Person(name){  
        this.name = name;  
};  
Person.prototype.getName = function(){  
            return this.name;  
        };  
var personOne = new Person("Diego");  
var personTwo = new Person("Filippo");  
console.log(personOne.getName()); // prints Diego  
console.log(personTwo.getName()); // prints Filippo  
console.log(personOne.getName === personTwo.getName) //prints true 

7. Singleton

Иногда вам может потребоваться убедиться, что существует только один экземпляр определенного класса. Получить Singleton в Javascript так же просто, как определить и вызвать конструктор в одно и то же время: просмотреть прозрачность?

var singleton = new function(){  
    this.name = "ApplicationName";  
};  

Ответ 3

Первый и третий подход почти одинаковы, так как они создают как объектный литерал, являющийся прямым дочерним элементом класса Object. Разница между ними заключается в том, что в третьем подходе у вас может быть какая-то инкапсуляция свойств:

var obj = (function() {
    var prop = {};

    return {
        prop2: function(){ return prop };
    }
})();

По производительности вы можете подумать, что третий подход создает закрытие, в то время как первый не работает!

Однако во втором подходе вы просто создаете новый объект из анонимного класса, который не является прямым потомком класса Object.

Правильная форма второго подхода - это (по крайней мере, этот стандарт ecma):

var obj = new function() {
    var prop1 = value1;

    this.prop2 = value2;
}();

Разница между подходами 2 и 3 - это только их цепочка наследования: (предполагая, что obj2 - из второго подхода, а obj3 - из третьего подхода)

obj2.__proto__ == Object.prototype;  // false
obj3.__proto__ == Object.prototype;  // true

obj2 создается из анонимного класса:

obj2.__proto__.__proto__ == Object.prototype;  // true (there 2 level of inheritance here)

Ответ 4

Подход 1
Это единственный объект, без класса, и вы не можете определить более простой, если он сложный

var obj = {
   prop: value
}

Подход 2
Не анонимная функция. Он создаст объект из "класса", нормальная функция будет сохранена как имя класса и может создавать несколько объектов одного типа, как это показано ниже:

var Bycicle= function() {
    var prop1 = value1;

    this.prop2 = value2;
}
var obj1 = new Bycicle(),
    obj2 = new Bycicle();

Подход 3
Анонимная функция, переменные извне функции не могут мешать переменным внутри функции:

var a = 10;
var obj = (function() {
    alert(a); // Alerts undefined
    var prop1 = value1;
    alert(prop1); // alerts the value of value1
    return {
        prop2: value2;
    }
})(); // Within the () you can pass arguments to the anonymous function.

Подробнее об анонимных функциях: http://helephant.com/2008/08/23/javascript-anonymous-functions/

Другие подходы
Также существует Object.create() и new Object() для создания новых объектов, которые оба совпадают с подходом 1.

Заключение
В конце концов, объект всегда будет тем же, за исключением 3-го, потому что он анонимный.

Ответ 5

Там также:

var obj = Object.create({prop: ...});

Это работает, установив прототип. Гораздо эффективнее использовать прототип, если вы собираетесь иметь несколько объектов, разделяющих свойства или методы.

var proto = {foo: function() {}},
    obj1 = Object.create(proto),
    obj2 = Object.create(proto),
    obj3 = {foo: function() {}},
    obj4 = {foo: function() {}};

В этом примере obj1 и obj2 используют функцию "foo", определенную в "proto". Между тем, obj3 и obj4 имеют свой собственный "foo". Если вы создаете множество объектов с большим количеством свойств, это может существенно повлиять на потребление памяти и даже на производительность.

Это преимущество используется при использовании ключевого слова "новое", если вы используете именованную функцию и назначаете свойства прототипу функции (например: f.prototype.prop) перед использованием нового.

Ответ 6

Не существует большой разницы между подходами 2 и 3 для одноразовых объектов. (Если бы вы назвали функцию, используемую в подходе 2, вы бы определили конструктор многократного использования.) Мое впечатление таково, что подход 3 чаще используется для этих ситуаций, но я не вижу в них большой разницы.

Следует отметить, что оба подхода 2 и 3 могут принимать аргументы:

var approach2Obj = new function(formalArg) {
    var privateProp = ...;
    this.publicProp = ...;
    // more constructor logic
)(actualArg);

var approach3Obj = (function(formalArg) {
    var privateProp = ...;
    // more creation logic
    return {
        publicProp : ...;
    };
}(actualArg));

P.S. Как отмечает @Алексей Лебедев в своем ответе, одно отличие между двумя (возможно, единственное) состоит в том, что approach2Obj.constructor и approach3Obj.constructor будут разными. approach3Obj.constructor будет тождественно Object, а approach2Obj.constructor будет анонимной функцией.

Ответ 7

В вашем вопросе должен быть 2 подхода, потому что Подход 3 похож на Подход 1 только способ создания, который является функцией самозапуска.

О различии при создании объекта, например Подход 1, вы можете думать об этом как о объекте с только статической функцией, например, в java. поэтому он всегда жив, и вы не делаете экземпляр из него (похожий на singleton) - поэтому, когда вы делаете этот объект:

var obj = {
    prop: value,
    func: function(){
     alert(this.prop);
    }
};

Вы можете вызвать его немедленно:

obj.prop = 'something else';
obj.func();

Подход 2 (без нового, как у вас есть) - это классический объект, который вы можете создавать экземпляры - наследовать (с помощью js-трюков) и т.д.:

function Person(firstName,lastName){ // or var Person = function(...
   this.firstName = firstName;
   this.lastName= lastName;

   this.getFullName = function(){
      return this.firstName + ' ' + this.lastName;
   }
}

//use
var person1 = new Person('yair','lapid');
var person2 = new Person('Naftali','Bennet');

you can put it in an array etc...
var arr = [person1,person2, new Person('shelly','yekimovits')];

Ответ 8

Чтобы понять подход 2, читателю нужно знать некоторые довольно технические вещи о том, как работает новое ключевое слово. В частности, это фактически вызовет анонимную функцию как конструктор, а не создает экземпляр нового объекта функции и выгружает его в переменную obj.

Чтобы понять подход 3, читателю нужно просто понять шаблон IIFE. Этот шаблон стал очень распространенным в javascript-коде за последние два года, и, вероятно, именно поэтому эта версия чаще используется.

Обе версии используются для создания инкапсуляции, и обе версии требуют знания сложной языковой функции для понимания. Однако языковая функция, требуемая в третьем подходе, более известна, чем языковая функция, необходимая для понимания подхода два. Вот почему подход три чаще используется в дикой природе.