Метод "метод" в книге Крокфорда: Javascript: Хорошие детали
Дуглас Крокфорд написал в своей книге (стр. 4):
Всюду по книге метод method
используется для определения новых методов. Это его определение:
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
Затем он начинает использовать этот method
для добавления метода в Number, String, Function, Object, Array, RegExp
, и вот полный список:
P33:
Number.method('integer', function () {...});
String.method('trim', function () {...});
P40 (не уверен, что есть опечатка на странице 41: end()):
String.method('deentityify', function () {...}());
P43 и P44:
Function.method('curry', function () {...});
P47 (я смущен здесь, не знаю, почему Крокфорд определяет метод new
, и он, кажется, никогда не использует метод new
в книге):
Function.method('new', function () {...});
P48:
Function.method('inherits', function (Parent) {...});
P54:
Object.method('superior', function (name) {...});
P62:
Array.method('reduce', function (f, value) {...});
P79:
Array.method('pop', function () {...});
Array.method('push', function () {...});
Array.method('shift', function () {...});
P82:
Array.method('splice', function (start, deleteCount) {...});
P84:
Function.method('bind', function (that) {...});
P88:
RegExp.method('test', function (string) {...});
String.method('charAt', function (pos) {...});
P90 (не уверен, есть ли опечатка на странице 91: end()):
String.method('entityify', function () {...}());
Определение method
основано на Function
, почему его можно использовать в Number, String, Object, Array, RegExp
кроме Function
? И может ли этот method
использоваться для другого типа данных?
Еще один маленький вопрос: на стр. 63 и 64 определение Array.dim, Array.matrix, Array.identity
не использовалось выше method
, почему?
Ответы
Ответ 1
Все нативные функции в JavaScript наследуются от Function.prototype
. Number
, String
, Object
, Array
и RegExp
- все функции, поэтому они наследуют от Function.prototype
.
method
предназначен для вызова функций-конструкторов. Его задача состоит в том, чтобы сделать функцию, которую вы ей поставляете, в метод, который существует для каждого объекта, созданного функцией-конструктором, на которую вы назвали method
. Вы заметите, что в тех функциях, которые Крокфорд переходит на method
, он использует this
, который является ссылкой на объект, на который был вызван метод. Array.dim
, Array.matrix
и Array.identity
не используют this
, потому что они работают независимо от любого конкретного массива и, следовательно, не должны быть методами отдельных объектов массива. Для удобства они назначаются как функции функции Array
: они могут одинаково хорошо существовать как функции в глобальной области.
Ответ 2
Как в сторону, на P40:
End() означает "использовать функцию, возвращаемую этой функцией", а не внешнюю функцию, которая возвращает его.
Если он оставил final(), вызов deentityify вернул бы функцию, а не строку.
В Дугласе Крокфорде собственные слова:
Мы немедленно вызываем функцию, которую мы только что сделали с оператором(). Этот вызов создает и возвращает функцию который становится методом deentityify.
Ответ 3
Решение, данное @Tim Down, является точным, но не полностью ясным.
Объект функции vs Объект экземпляра объекта
Прежде всего, в javascript функция также является объектом. Из этого я имею в виду не объект, созданный конструкцией new(), а сама функция. Чтобы избежать путаницы, я бы назвал такие объекты как Объект функции, а для объекта, созданного с помощью функции new() функции, как Объект экземпляра функции.
_ свойства прото и _ прототипа
Любой объект функции в javascript имеет два свойства: _ proto _ и прототип. Более того, любой объект экземпляра Function (созданный с использованием нового конструктора) имеет свойство _ proto _. _ proto_ - это то, что определяет наследование. Некоторый хороший ресурс по этому вопросу можно найти в
http://zeekat.nl/articles/constructors-considered-mildly-confusing.html
Как определено наследование?
Объект objA наследует другой объект objC, если objA и objC связаны через любое число _ proto _. Итак, если objA имеет _ proto_, равный objB, а objB имеет _ proto _, равный objC, то objA наследует objB и objC, тогда как objB наследует objC.
Что подразумевается под наследованием?
Это означает, что любой наследующий объект может использовать любое свойство наследуемого объекта.
Что такое Function.prototype
Это объект, которому ссылается _ proto _ каждого объекта функции. Это означает, что каждый объект Function имеет доступ к свойствам Function.prototype, поскольку каждый объект Function наследует объект Function.prototype. Это также означает, что если свойство method добавлено в объект Function.prototype, оно будет доступно для всех возможных объектов Function в javascript. Это включает в себя строки, число и т.д.
this.prototype [name] = func;
это относится к объекту функции, когда "метод" вызывается из объекта функции s, например Number, String и т.д. Это означает, что теперь мы имеем новое свойство в Объект функции с именем "name" и его функцией "func".
Что хорошего в прототипе свойство Объект функции
Объект < " → ссылается на объект экземпляра _ proto _, созданный с использованием этой функции новая конструкция.
Если выполнено следующее:
Number.method('integer', function() {...});
то Number.prototype имеет этот целочисленный метод, определенный в нем. Это означает каждый экземпляр объекта , например. new Number (2.4), "наследует" это новое свойство "целое" от Number.prototype, так как этот экземпляр объекта будет иметь свой _ proto _ для параметра Number.prototype.
Ответ 4
Попробуйте использовать этот прототип метода:
String.prototype.deentityify = function () { ... }
Тогда:
document.writeln('<">'.deentityify( ));
Мы можем видеть:
<">
Ответ 5
Пример: Currying можно переписать следующим образом, если кто-то застрял. См. jsFiddle demo
Function.prototype.curry = function ( ) {
var slice = Array.prototype.slice;
var args = slice.apply(arguments);
var that = this;
return function () {
return that.apply(null,args.concat (slice.apply(arguments)));
}
};
var add = function(a, b)
{
return a + b;
}
var add1 = add.curry(1);
document.writeln(add1(6)); // 7