2015-11-23 5 views
6

Согласно this, функции наследуют от Function и Function от Function.prototype в свою очередь:разница между функцией и Function.prototype

Глобальный Function объект не имеет методов или свойств его собственной, однако, так как это сама функция наследует некоторые методы и свойства через цепочку прототипов от Function.prototype.

В чем смысл Function.prototype? Почему бы не переместить свои свойства на Function и не дать Function.prototype быть undefined? Функции будут получены из Function.

То же самое касается Object и т.д.

+3

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

+0

> «Функции будут получены из функции вместо». Поверьте, это ваш источник путаницы. Не знаете, где именно вы это читали, но функции не могут быть получены из функций в прототипном смысле. –

+0

@ nikc.org Хорошо, но почему из 'Function.prototype'? Или это не действительно наследуемые свойства, если мы выполняем 'f.prototype = Function', где' f' является функцией? Я имею в виду, если вы хотите наследовать от функции, вы делаете 'f.prototype = super_f', а не' f.prototype = super_f.prototype', правильно? – Downvoter

ответ

6

функции наследуют от Function

Вы цитируете MDN свободно. То, что он на самом деле говорит это:

функциональные объекты наследуют от Function.prototype

Обратите внимание, что на странице MDN, начальное слово «функция» в приведенном выше предложении капитализируются, но только потому, что на начало предложения, а не потому, что оно относится к объекту JS Function. Это относится к обычным старым функциям, объявленным как function() { }.

Помните, что MDN написано простым смертным. Я бы предпочел, чтобы они не использовали слова «наследовать» и «наследование», не говоря уже о «полученных». У JS нет понятия наследования в строгом смысле этого слова. Если вы используете эту терминологию, вы в конечном итоге запутаетесь. У JS есть прототипы, связанные с объектами. При доступе к объекту объекта, если он не найден, проконсультируется с прототипом. Если их не найти, поскольку прототип также является объектом с прототипом, проконсультируйтесь с прототипом, и так далее по цепочке.

Следовательно, вышеприведенное предложение было бы лучше написано как «функциональные объекты имеют в качестве своего прототипаFunction.prototype».

Объект JS Function не связан непосредственно с Function.prototype, кроме того факта, что Function.prototype является собственностью Function, и, так как Function объект сам по себе является функцией, она сама по себе имеет Function.prototype как его прототип. Независимо от того, какие свойства могут или не могут присутствовать на Function, или висели на нем вами, не имеют ничего общего с цепочкой прототипов и не «унаследованы» кем-либо.

Когда вы делаете (function() { }).call(), свойство/метод call сначала просматривается на самом объекте функции; если он там не существует, как обычно это не будет, тогда он проверяется на прототипе, который присваивается по существу, когда объявлена ​​функция, которая равна Function.prototype. Где еще вы бы поставили такие методы, как call или apply, если не на Function.prototype? Что еще вы могли бы назвать прототипом, автоматически назначенным для функций, отличных от Function.prototype?

В качестве примечания обратите внимание, что Function.call правильно разрешит внутреннюю функцию call. Зачем? Не потому, что там находится call, либо потому, что это происходит из-за того, что регулярные функции «наследуют» call, а скорее потому, что, как я упоминал ранее, Function сам по себе является функцией, и поэтому имеет прототип Function.prototype, call можно найти на его прототип цепи.

В чем смысл Function.prototype? Почему бы не переместить свои свойства на Function и не удалось определить Function.prototype? Функции будут получены из Function.

X.prototype является свойством X, используемым в качестве прототипа для объектов, созданных с использованием X в качестве конструктора. Поэтому для назначения правильного прототипа объектам, созданным с использованием Function в качестве конструктора (который включает функции, объявленные как function x() { }), прототип должен быть представлен как свойство prototype на Function.

+0

Crap, полностью забытый 'Function.prototype' - это просто свойство, а не отдельный объект. Во всяком случае, почему бы не переместить свойства объекта, на которые ссылается 'Function.prototype', в' Function'? Если у вас есть две функции: 'f' и' g', то вы скажете 'f.prototype = g', а не' f.prototype = g.prototype', правильно? И в отношении «он сам имеет Function.prototype как свой прототип» - не приведет ли это к бесконечной рекурсивной петле? И основываясь на этом, когда компилятор перестает подниматься вверх по цепи прототипов? – Downvoter

+0

Нет, поскольку прототипом 'Function.prototype' является' Object.prototype'. Двигатель перестает подниматься по цепи прототипов, когда он сталкивается с объектом без прототипа. 'Object.getPrototypeOf (Object.prototype) == null'. –

+0

Итак, 'Function.prototype.prototype === Object.prototype'? И не «он сам имеет Function.prototype в качестве своего прототипа». означает, что 'Function.prototype === Function.prototype'? Да, это очевидно, но я все равно не понимаю. :( – Downvoter

2

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

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

Его легче увидеть различия с обычными объектами или массивами, а не функции

function Foo(){ 
    this.bar = []; 
} 
var fooObj1 = new Foo(); 
var fooObj2 = new Foo(); 

fooObj1.bar.push("x"); 
alert(fooObj2.bar) //[] 
as opposed to: 

function Foo(){ 
} 

Foo.prototype.bar = [] 
var fooObj1 = new Foo(); 
var fooObj2 = new Foo(); 

fooObj1.bar.push("x"); 
alert(fooObj2.bar) //["x"] 
+1

Все это правда, но не совсем то, о чем говорил OP, что является структурой наследования для самих функций. –

0

Вам нужно Function.prototype, если вы хотите расширить функции, считают это:

Function.prototype.moo = 5; 
function x() { }; 
console.log(x.moo); // 5 

каждую функцию вы делаете теперь имеет свойство moo, по сравнению с:

Function.quack = 6; 
function b() {}; 
console.log(b.quack); // undefined 

Это не верно, если вы просто пощечины собственности на Function. Каждая функция не наследует свойства, назначенные Function, поэтому вам необходимо Function.prototype.

+0

«Это неправда, если вы просто удаляете свойство на' Function' »- почему бы и нет? Я собираюсь возобновить чтение моей аккуратной книги, возможно, мой вопрос просто основан на моем «незнании». – Downvoter