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

Что происходит в технике создания объектов Крокфорда?

Есть только 3 строки кода, и все же у меня возникли проблемы с полным пониманием этого:

Object.create = function (o) {
    function F() {}
    F.prototype = o;
    return new F();
};
newObject = Object.create(oldObject);

(из Прототипное наследование)

  • Object.create() начинается с создания пустой функции с именем F. Я думаю, что функция является своего рода объектом. Где хранится этот объект F? По-моему, глобально.

  • Далее наш oldObject, переданный как o, становится прототипом функции F. Функция (т.е. Объект) F теперь "наследует" от нашего oldObject, в том смысле, что разрешение имени будет проходить через него. Хорошо, но мне любопытно, какой прототип по умолчанию для объекта Object? Это также верно для функции-объекта?

  • Наконец, F создается и возвращается, становясь нашим newObject. Строго ли здесь операция new? Разве F не предоставляет то, что нам нужно, или существует критическое различие между объектами-функциями и не-функциональными объектами? Очевидно, что с помощью этой техники невозможно будет иметь конструкторскую функцию.

Что произойдет в следующий раз Object.create()? Переписывается ли глобальная функция F? Разумеется, он не используется повторно, потому что это изменит ранее настроенные объекты. И что произойдет, если несколько потоков вызовут Object.create(), есть ли какая-либо синхронизация, чтобы предотвратить условия гонки на F?

4b9b3361

Ответ 1

1) Object.create() начинается с создавая пустую функцию F. Я думаю, что функция является видом объекта. Где этот объект F хранится? По-моему, глобально.

Нет, он хранится в локальной области функции Object.create, каждый раз при вызове Object.create эта функция F будет воссоздана.

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

if (typeof Object.create !== "function") {
  Object.create = (function () {
    function F() {} // created only once
    return function (o) {
      F.prototype = o; // reused on each invocation
      return new F();
    };
  })();
}

2) Далее наш oldObject, переданный как o, становится прототипом функции F. Теперь функция (т.е. Объект) F "наследует" наш старый объект, в что разрешение имени будет маршрутизироваться через это. Хорошо, но мне любопытно, что прототип по умолчанию предназначен для Объект Object? Это справедливо и для функция-объект?

Все объекты имеют внутреннее свойство, которое создает цепочку прототипов, это свойство известно как [[Prototype]], это внутреннее свойство, хотя некоторые реализации позволяют вам получить доступ к нему, например mozilla, с свойством obj.__proto__.

По умолчанию [[Prototype]] при создании нового объекта, т.е. var obj = {}; есть Object.prototype.

Все функции имеют свойство prototype, это свойство используется, когда функция используется как Constructor, вызывается с помощью new.

Новый экземпляр объекта, созданный за кулисами, и этот объект [[Prototype]] установлен в его свойство Constructor prototype.

3) Наконец, F создается и вернулся, став нашим новым объектом. Является "новая" операция строго необходима Вот? Разве F не дает того, что нам нужно, или есть критический разница между функциональными объектами и не-функциональные объекты? Ясно, что это не будет возможности иметь конструктор, используя это Методика.

Да, в этом методе необходим оператор new.

Оператор new является единственным стандартным способом установки внутреннего свойства [[Prototype]] объекта, если вам интересно, как он работает, вы можете взглянуть на [[Construct]] внутренняя операция.

Что произойдет в следующий раз Вызывается Object.create()? Является глобальным функция F перезаписана? Конечно, это не используется повторно, потому что это изменит ранее настроенных объектов. А также что произойдет, если вызовет несколько потоков Object.create(), есть ли какие-либо синхронизация для предотвращения гонки условия на F?

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

Обратите внимание, что эта реализация вряд ли соответствует Object.create, описанному в ECMAScript 5th Edition Specification, в этом методе вы можете передать дескриптор свойства для инициализации объекта.

Все разработчики браузеров внедряют его (уже доступны в Firefox 3.7 alphas, последние версии Wekit Nightly Builds и Chrome 5 Beta), поэтому я бы порекомендовал вам хотя бы проверить, существует ли встроенная реализация, прежде чем переопределять ее.

Ответ 2

1) Функция действительно является своего рода объектом. Функциональный объект с идентификатором F создается каждый раз при вызове Object.create и доступен только с этим идентификатором в этом выполнении Object.create. Поэтому каждый раз, когда вызывается Object.create, вы получаете другой объект функции F. Этот функциональный объект живет как свойство constructor объекта, возвращаемого Object.create.

2)

F теперь "наследует" от нашего oldObject, в том смысле, что разрешение имен будет маршрут через него

Это не совсем правильно. Присвоение объекту someObject свойству prototype функции просто означает, что прототип любого будущего объекта, созданного вызовом этой функции в качестве конструктора, будет someObject.

3) new абсолютно необходим для этой техники. Только вызывая функцию как конструктор, он создает новый объект, и этот прототип объекта (который обычно недоступен) устанавливается в свойство конструктора prototype. Нет другого (стандартизованного) способа установки прототипа объекта.

Наконец, JavaScript в браузерах однопоточный, поэтому условия гонки, такие как вы описываете, невозможны.

Ответ 3

Ваше основное недоразумение здесь в том, что F имеет глобальный охват. Он объявляется в теле Object.create и, следовательно, находится только в области видимости внутри этого блока методов.

Ответ 4

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

Этот метод уже является конструктором объекта, так как он возвращает новый F(), но не могут быть заданы значения свойств, например, для нового человека ( "Джон", "Смит" ). Однако, если код Object.create изменен, возможно создание экземпляра. Например, объект sarah ниже может быть создан и создан с использованием Object.creator и наследует метод getName.

var girl = {
   name: '',
   traits: {},
   getName: function(){return this.name}
}

var sarah = Object.creator(girl, 'Sarah', {age:29,weight:90})

Затем объект sarah будет состоять из собственных свойств {name: 'Sarah', traits: {age: 9, weight: 49}}, а прототип унаследованного sarah.getName() будет производить "Sarah".

Следующий метод основан на собственных свойствах, перечисляемых с помощью параметра "for (prop in o)" в порядке создания. Хотя это не гарантировано спецификациями ECMA, этот пример (и несколько более сложных) работал для всех основных браузеров (4), проверенных, был использован hasOwnProperty(), в противном случае нет.

Object.creator = function(o) {
   var makeArgs = arguments 
   function F() {
      var prop, i=1, arg, val
      for(prop in o) {
         if(!o.hasOwnProperty(prop)) continue
         val = o[prop]
         arg = makeArgs[i++]
         if(typeof arg === 'undefined') break
         this[prop] = arg
      }
   }
   F.prototype = o
   return new F()
}

У официального объекта ECMA Object.create есть необязательный 2-й параметр, свойствоОбъект, который может создавать значения свойств, но это скорее объект, чем обычный список, и выглядит неудобно. Например. Я верю: -

o2 = Object.create({}, { p: { value: 42, writable: true, enumerable: true, configurable: true } });

эквивалентен гораздо более старому способу: -

o2 = new function(p) { this.p=p }(42)

и

o2 = Object.creator({p:''}, 42)