Недавно я наткнулся на Object.create()
метод в JavaScript и пытаюсь понять, чем он отличается от создания нового экземпляра объекта new SomeFunction()
и когда вы хотите использовать один поверх другого.
Рассмотрим следующий пример:
var test = {
val: 1,
func: function() {
return this.val;
}
};
var testA = Object.create(test);
testA.val = 2;
console.log(test.func()); // 1
console.log(testA.func()); // 2
console.log('other test');
var otherTest = function() {
this.val = 1;
this.func = function() {
return this.val;
};
};
var otherTestA = new otherTest();
var otherTestB = new otherTest();
otherTestB.val = 2;
console.log(otherTestA.val); // 1
console.log(otherTestB.val); // 2
console.log(otherTestA.func()); // 1
console.log(otherTestB.func()); // 2
Обратите внимание, что одинаковое поведение наблюдается в обоих случаях. Мне кажется, что основными различиями между этими двумя сценариями являются:
- Используемый объект
Object.create()
фактически формирует прототип нового объекта, тогда как вnew Function()
заявленных свойствах / функциях не формируется прототип. - Вы не можете создавать замыкания с
Object.create()
синтаксисом, как с функциональным синтаксисом. Это логично, учитывая объем лексического (против блочного) типа JavaScript.
Являются ли приведенные выше утверждения правильными? И я что-то упустил? Когда бы вы использовали один поверх другого?
РЕДАКТИРОВАТЬ: ссылка на jsfiddle версию приведенного выше примера кода: http://jsfiddle.net/rZfYL/
Ответы:
Да,
Object.create
создает объект, который наследует непосредственно от объекта, переданного в качестве первого аргумента.С функциями конструктора вновь созданный объект наследует от прототипа конструктора, например:
В приведенном выше примере
o
наследуется непосредственно отSomeConstructor.prototype
.Здесь есть разница:
Object.create
вы можете создать объект, который ни от чего не наследует,Object.create(null);
с другой стороны, если вы установитеSomeConstructor.prototype = null;
новый объект, от которого будет наследоватьсяObject.prototype
.Ну, вы можете создавать замыкания, например, используя аргумент дескрипторов свойств:
Обратите внимание, что я говорю о
Object.create
методе ECMAScript 5-го издания , а не об обтекателе Крокфорда.Этот метод начинает реализовываться в последних браузерах, проверьте эту таблицу совместимости .
источник
foo;
разрешается в текущей лексической среде . 2) Чтобы обеспечить простой способ реализации наследования, это действительно мощная конструкция. IMO Я бы использовал его, потому что он действительно простой и легкий, но для производственного кода нам все еще нужно немного подождать, пока ES5 не получит широкую поддержку. О недостающих функциях, факте создания «нетронутого» объекта,Object.create(null);
не хватало, действительно полезно реализовать надежные объекты, подобные хеш-таблицам ...Object.create(null)
значит, вам не нужно использоватьhasOwnProperty()
дерьмо при итерации, потому что она не наследует ничего ??? Мне это нравится - спасибо. Конечно, все еще будут делать,hasOwnProperty
потому что не все будут использовать,Object.create(null)
так что я не уверен, что это реальная выгода ... Пока я нашел другие "преимущества"Object.create()
совершенно неубедительными.Проще говоря,
new X
этоObject.create(X.prototype)
с дополнительнойconstructor
функцией запуска . (И даетconstructor
возможностьreturn
фактическому объекту, который должен быть результатом выражения вместоthis
.)Вот и все. :)
Остальные ответы просто сбивают с толку, потому что, очевидно, никто другой не читает определение того
new
или другого. ;)источник
Вот шаги, которые происходят внутри для обоих вызовов:
(Подсказка: единственная разница в шаге 3)
new Test()
:new Object()
объектobj.__proto__
наTest.prototype
return Test.call(obj) || obj; // normally obj is returned but constructors in JS can return a value
Object.create( Test.prototype )
new Object()
объектobj.__proto__
наTest.prototype
return obj;
Так что в основном
Object.create
не выполняет конструктор.источник
new
основном дублируются все функции, в то времяObject.create
как нет.Позвольте мне попытаться объяснить (подробнее на блоге ):
Car
конструкторvar Car = function(){}
, это то , как вещи внутри: У нас есть одна{prototype}
скрытая ссылка наFunction.prototype
который не доступен и однаprototype
ссылка ,Car.prototype
которая доступна и имеет фактическийconstructor
изCar
. И Function.prototype, и Car.prototype имеют скрытые ссылки наObject.prototype
.Когда мы хотим создать два эквивалентных объекта, используя
new
оператор иcreate
метод, мы должны сделать это следующим образом:Honda = new Car();
иMaruti = Object.create(Car.prototype)
. Что происходит?Honda = new Car();
- Когда вы создаете такой объект, на{prototype}
него указывает скрытое свойствоCar.prototype
. Так что здесь,{prototype}
объект Honda будет всегдаCar.prototype
- у нас нет никакой возможности изменить{prototype}
свойство объекта. Что если я захочу изменить прототип нашего вновь созданного объекта?Maruti = Object.create(Car.prototype)
- Когда вы создаете такой объект, у вас есть дополнительная возможность выбрать{prototype}
свойство вашего объекта . Если вы хотите, чтобы Car.prototype использовался{prototype}
в качестве параметра, передайте его в качестве параметра функции. Если вы не хотите какой - либо{prototype}
для вашего объекта , то вы можете передатьnull
так:Maruti = Object.create(null)
.Заключение. Используя этот метод,
Object.create
вы можете свободно выбирать{prototype}
свойство объекта . Уnew Car();
вас нет этой свободы.Предпочтительный способ в OO JavaScript:
Предположим, у нас есть два объекта
a
иb
.Теперь предположим, что
a
есть несколько методов, к которымb
также нужен доступ. Для этого нам требуется наследование объекта (a
должно быть прототипом,b
только если мы хотим получить доступ к этим методам). Если мы проверим прототипыa
иb
тогда мы узнаем, что они разделяют прототипObject.prototype
.Проблема - мы хотим, чтобы объект
a
был прототипомb
, но здесь мы создали объектb
с прототипомObject.prototype
. Решение - ECMAScript 5 введенObject.create()
для легкого достижения такого наследования. Если мы создадим объект,b
как это:тогда,
Итак, если вы делаете объектно-ориентированные сценарии,
Object.create()
это очень полезно для наследования.источник
a.isPrototypeOf(b);
вернется,false
что правильно, потому что оба объекта разные и указывают на разную память. Правильный способ сделать это сnew
оператором здесь. - jsfiddle.net/167onunp .Эта:
а также
очень похожи. Одним из важных отличий является то, что на
new Foo
самом деле выполняется код конструктора, тогда какObject.create
не будет выполняться такой код, какОбратите внимание, что если вы используете двухпараметрическую версию,
Object.create()
вы можете делать гораздо более мощные вещи.источник
Object.create
в простейшей форме, подобной этой, позволяет вам исключить функции конструктора из вашего кода, используя преимущества наследования прототипов.Разница заключается в так называемом «псевдоклассическом и прототипном наследовании». Рекомендуется использовать только один тип в вашем коде, не смешивая их.
В псевдоклассическом наследовании (с оператором «new») представьте, что вы сначала определяете псевдокласс, а затем создаете объекты из этого класса. Например, определите псевдокласс «Персона», а затем создайте «Алиса» и «Боб» из «Персона».
В наследовании прототипа (с использованием Object.create) вы непосредственно создаете определенного человека «Алису», а затем создаете другого человека «Боб», используя «Алису» в качестве прототипа. Здесь нет «класса»; все объекты.
Внутренне JavaScript использует «прототипное наследование»; «псевдоклассический» путь - это просто немного сахара.
Смотрите эту ссылку для сравнения двух способов.
источник
Резюме:
1) с
new
ключевым словом следует отметить две вещи;а) функция используется в качестве конструктора
б)
function.prototype
объект передается в__proto__
свойство ... или там, где__proto__
это не поддерживается, это второе место, где новый объект ищет свойства2) вместе с
Object.create(obj.prototype)
вами вы создаете объект (obj.prototype
) и передаете его намеченному объекту ... с той разницей, что теперь новый объект__proto__
также указывает на obj.prototype (пожалуйста, ссылки на xj9 для этого)источник
Варианты создания объекта.
Вариант 1 : ' new Object () ' -> Конструктор объекта без аргументов.
Вариант 2 : « новый объект (персона) » -> конструктор объекта с аргументом.
Вариант 3.1 : « Объект.создание (персона) ». Используйте Object.create с простым объектом 'person'. Object.create (person) создаст (и вернет) новый пустой объект и добавит свойство __proto__ к тому же новому пустому объекту. Это свойство '__proto__' будет указывать на объект 'person'.
Вариант 3.2 : « Object.create (Object.prototype) ». Используйте Object.create со встроенным объектом -> 'Object.prototype'. Object.create (Object.prototype) создаст (и вернет) новый пустой объект и добавит свойство «__proto__» к тому же новому пустому объекту. Это свойство '__proto__' будет указывать на объект 'Object.prototype'.
Вариант 4 : « новая функция SomeFunction () »
источник
Внутренне
Object.create
делает это:Синтаксис устраняет иллюзию того, что JavaScript использует классическое наследование.
источник
Object.create
делает намного больше, вы можете определять свойства по дескрипторам свойств и создавать объект, который не наследует от чего-либо (Object.create(null);
), такого типа прокладок следует избегать, потому что вы не можете его эмулировать. поведение на ES3. Больше информацииObject.create
.Соответственно этому ответу и данному видео
new
ключевое слово делает следующие вещи:Создает новый объект.
Связывает новый объект с функцией конструктора (
prototype
).Делает
this
переменную указателем на новый объект.Выполняет функцию конструктора, используя новый объект и неявное выполнение
return this
;Назначает имя функции конструктора для свойства нового объекта
constructor
.Object.create
выполняет только1st
и2nd
шаги !!!источник