Как вы сами сказали: у вас есть функция object. Функции — это объекты в JS, точно так же, как литералы Object, массивы или что-либо еще: функции можно по желанию назначать свойства и методы:
var someAnonFunction = function(foo)
{
console.log(this);
console.log(this === someAnonFunction);//will be false most of the time
};
someAnonFunction.x = 123;//assign property
someAnonFunction.y = 312;
someAnonFunction.divide = function()
{
console.log(this === someAnonFunction);//will be true most of the time
return this.x/this.y;//divide properties x & y
};
someAnonFunction.divide();
В этом случае функциональному объекту, на который ссылается someAnonFunction
, была назначена ссылка на анонимную функцию, называемую divide
(ну, в любом случае, ссылка на анонимную функцию была названа разделять). Таким образом, здесь нет никакого участия прототипа. Имейте в виду, как вы сами говорите: все объекты можно проследить до Object.prototype
, просто попробуйте это:
console.log(someAnonFunction.toString === Function.prototype.toString);//functions are stringified differently than object literals
console.log(someAnonFunction.hasOwnProperty === Object.prototype.hasOwnProperty);//true
Или, возможно, это более понятно: простая схема того, как вызов метода/свойства преобразуется в значение в JS:
[ F.divide ]<=========================================================\ \
F[divide] ===> JS checks instance for property divide | |
/\ || | |
|| || --> property found @instance, return value-------------------------------| |
|| || | |
|| ===========> Function.prototype.divide could not be found, check prototype | |
|| || | |
|| ||--> property found @Function.prototype, return-----------------------| |
|| || | |
|| ==========> Object.prototype.divide: not found check prototype? | |
|| || | |
|| ||--> property found @Object.prototype, return---------------------|_|
|| || |=|
|| =======>prototype is null, return "undefined.divide"~~~~~~~~~~~~~~~|X|
|| \ /
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< TypeError can't read property 'x' of undefined
Из этого следует, что если вы хотите, чтобы приведенный выше код работал с использованием прототипов, вам придется расширить своего рода прототип (в данном случае Function.prototype
). Помните, что это не рекомендуется, поскольку изменение "родных" прототипов часто вызывает неодобрение. Еще:
Function.prototype.divide = function (a, b)
{
a = +(a || 0);//coerce to number, use default value
b = +(b || 1) || 1;//division by zeroe is not allowed, default to 1
return a/b;
};
function someFunction ()
{
return 'someString';
};
var another = function(a, b)
{
return a + b;
};
someFunction.divide(12, 6);//will return 2
another.divide(12, 4);//3
В обоих случаях объект функции, на который ссылается имя (someFunction
или another
), будет просканирован на наличие свойства с именем divide
, которое не будет найдено. Однако затем он просканирует Function.prototype
, где такое свойство найдено.
Если бы это было не так, JS также проверил бы Object.prototype
, и если это не удалось, в конечном итоге выдаст ошибку.
Некоторое время назад я опубликовал довольно длинные ответы на SO по этому вопросу:
Что делает my.class.js таким быстрым? (имеет дело с цепочками прототипов)
Объекты и функции в javascript (резюме функций ‹=> объекты ‹=> конструкторы)
В чем разница между этими тремя шаблонами определений классов в JavaScript? (еще немного информации)
Javascript — динамическое изменение содержимого функции (смутно затрагивает анонимный функции, присваиваемые переменным и свойствам и изменяющие их контекст)
person
Elias Van Ootegem
schedule
02.03.2013
var addNum = function(num1, num2) { this.divide = function(){} return num1 + num2; }
Думаю, да? - person Weishi Z   schedule 10.05.2016