2010-05-09 2 views
2

Я просто читаю о прототипах в JavaScript и Douglas Crockford предлагает и отличный способ выбрать прототип новых объектов, но может ли кто-нибудь объяснить (ниже), почему тип obj01 равен «объекту», когда я передаю его в функцию, поскольку это опытный образец?Javascript Prototyping Question

if (typeof Object.beget !== 'function') { 
    Object.beget = function (o) { 
     console.log(typeof o);//function 
     var F = function() {}; 
     F.prototype = o; 
     console.log(typeof F);//function 
     return new F(); 
    }; 
} 
var func01 = function(){}; 
var obj01 = Object.beget(func01); 
console.log(typeof obj01);//object 
console.log(typeof obj01.prototype);//object 

Я думал, что это будет

console.log(typeof obj01);//function 
console.log(typeof obj01.prototype);//function 

ответ

4

obj01 просто объект, который наследует от объекта функции, вы не можете создавать функции таким образом.

Оператор typeof возвращает "function" только в том случае, если его операнд сам по себе можно назвать.

Есть только три действительный способ создания функциональных объектов:

объявление функции: выражение

function name (/*arg, argn...*/) { 
} 

Функции:

var fn = function /*nameopt*/ (/*arg, argn...*/) { 
}; 

Конструктор функции:

var fn = new Function("arg", "argn", "FunctionBody"); 

Edit: В ответ на ваш комментарий, obj01, это просто объект, его прототип цепь содержит функциональный объект, а затем Function.prototype и затем Object.prototype, но это не делает объект вызываемая.

Вашего объект не отозван, функция только объекты, но у них есть некоторые специальных внутренних свойства, которые позволяют им вести себя так.

Объект является вызываемой только если он реализует внутреннюю [[Call]] свойства.

Есть другие внутренние свойства, которые функционируют объекты имеют, как [[Construct]], который вызывается, когда используется оператор new, в [[Scope]] имущества, которое хранит лексическую среду, в которой выполняется функция, и многое другое.

Если вы пытаетесь вызвать ваш объект, как если бы это была функция, вы будете иметь TypeError, потому что когда вы сделаете function call, объект должен иметь внутреннее свойство [[Call]].

Функциональные объекты должны иметь вышеуказанные внутренние свойства, и единственный способ, что они могут быть построены в тремя способами, которые я упоминал в начале, вы можете увидеть, как внутри функции создаются объекты here.

+0

Привет CMS, это было не то, что я пытался создать функцию. Я пытался понять наследование и прототипирование в JavaScript. Итак, если прототип моего нового объекта теперь является Function.prototype, почему мой новый объект не может быть вызван? Являются ли методы вызова и применения не частью прототипа функции, которую наследует мой новый объект? – screenm0nkey

+0

@Nick: Отредактировано для уточнения, пожалуйста, спросите, есть ли у вас какие-либо сомнения. – CMS

+0

Спасибо CMS. Это был очень тщательный ответ. Я действительно ценю твою помощь. У меня есть еще один вопрос. Когда вы говорите о цепочке прототипов объекта, это хранится в скрытом свойстве внутреннего прототипа? Я знаю, что функции имеют два свойства прототипа, один скрыт, а другой нет. – screenm0nkey

1

Его действительно очень просто.

Переменная F указывает на функцию, поэтому typeof F возвращает функцию «.

Но возвращаемое значение от F() - это объект, контекст выполнения (объект активации) или экземпляр класса, если хотите. Для получения дополнительной информации об этом читайте this excellent blog series.

Для этого typeof F() возвращает «объект».

Как показал Мартин в своем комментарии; изменить return new F(); на return F;. Это должно вернуть новую функцию с измененной цепочкой областей, используемой для создания нового «подкласса».

+0

Вы можете видеть, что он работает так, как вы ожидаете здесь http://jsbin.com/aruxa3/edit – Martyn

+0

@Martyn, который полностью пропускает точку этой функции 'beget', создает объект, который наследуется от другого ... – CMS

+0

@ Шон, значение 'new F();' просто объект (созданный [[['Construct'] (http://bclary.com/2004/11/07/#a-13.2.2)] ], он не имеет ничего общего с объектом активации, который в этом случае для 'beget' и' F' будет мусором, собранным после каждого вызова. – CMS