2013-04-19 3 views
22

Я видел несколько разных способов создания объектов в 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 создают замыкания, но в чем разница между ними.

+0

В подходе 2 ключевое слово 'new' не должно быть. – Halcyon

+2

@FritsvanCampen - Да, должно. Это создает новый объект из функции (анонимного) конструктора. –

+1

, если ключевое слово 'new' не существует, это будет класс. – macool

ответ

10

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

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

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

Верхний ответ Module pattern vs. instance of an anonymous constructor включает в себя цитаты из Дугласа Crockford, в котором он объясняет, почему он считает, что подход № 3 лучше, чем № 2.

+0

Ницца. Я не думал о свойстве 'constructor'. –

0

Не существует большой разницы между подходами 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. Как @Alexey Lebedev points out in his answer, одна разница между двумя (возможно, единственная) заключается в том, что approach2Obj.constructor и approach3Obj.constructor будут отличаться. approach3Obj.constructor будет идентичным Object, а approach2Obj.constructor будет анонимной функцией.

+0

Извините, в основном, prop1 указывает на частные переменные. Логика функции может продолжаться и использовать эти переменные ... Я обновлю, чтобы отразить это – Umair

+0

@Umair - Я не думаю, что мой ответ изменится. Подходы 2 и 3 в основном эквивалентны. –

4

Первый и третий подход почти одинаковы, так что они оба создают объектный литерал, который является прямым потомком класса 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 составляет от 2-го захода на посадку и obj3 от 3 подхода)

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

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

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

Что вы подразумеваете под «прямым ребенком»? –

+1

Любой литерал объекта наследуется непосредственно из 'Object.prototype', что делает его прямым потомком класса' Object': 'obj .__ proto__ == Object.prototype' –

0

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

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

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

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

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

Approach 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')]; 
+0

Подход 3 создает закрытие; подхода 1 нет. Это делает их совершенно разными. –

+0

Но это не вопрос - вы можете вызвать также регулярную функцию, возвращающую объект или самолет, возвращающий объект, - он спрашивает о разности создаваемых объектов - и это неправильное определение замыкания btw ... – Adidi

2

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

var obj = { 
    prop: value 
} 

подход 2
Беспоставочной анонимной функции.Это создаст объект из «класса», normalle функция сохраняется в качестве имени класса и может создать несколько объектов одного и того же типа легко, как показано ниже:

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-го, потому что это анонимно.

0

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

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

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

+0

Сотрудник однажды удаляет ключевое слово 'new' из анонимного конструктора, потому что он думал, что это опечатка. –

2

Там также:

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) перед использованием нового.

16

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

1. Конструктор Object

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

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. Функция/Prototype сочетание

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

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 так же просто, как определить и вызвать конструктор одновременно: посмотреть plainprint?

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

Что такое «просмотр прозрачности?» даже означает? – Taurus

Смежные вопросы