иллюстрировать
В JavaScript нет реальной перегрузки функций.
перегрузка функций
Имя функции такое же, список параметров функции другой (включая количество параметров и типов параметров), и разные операции выполняются в соответствии с разными параметрами.
Возьмем пример
function overload(a){
console.log('一个参数')
}
function overload(a,b){
console.log('两个参数')
}
// 在支持重载的编程语言中,比如 java
overload(1); //一个参数
overload(1,2); //两个参数
// 在 JavaScript 中
overload(1); //两个参数
overload(1,2); //两个参数
В JavaScript две функции с одинаковыми именами появляются в одной области видимости, и последняя перезаписывает первую, поэтому в JavaScript нет реальной перегрузки.
Но есть разные способы имитировать эффект перегрузки в JavaScript.
Сначала посмотрите на первый метод,объект аргументовреализовать
объект аргументов, представляет собой массивоподобный объект внутри функции, в котором хранятся все параметры, переданные функции при вызове функции.
function overload () {
if (arguments.length === 1) {
console.log('一个参数')
}
if (arguments.length === 2) {
console.log('两个参数')
}
}
overload(1); //一个参数
overload(1, 2); //两个参数
Этот пример очень прост: мы оцениваем свойство длины объекта arguments, чтобы определить, сколько есть параметров, а затем что делать.
Но если параметров мало, то к счастью, если параметров больше, то суждение нужно писать много, а это хлопотно.
Итак, давайте рассмотрим еще один классический пример Прежде чем рассматривать этот пример, давайте сначала посмотрим на требование, У нас есть объект пользователей, и свойство values объекта пользователей хранит некоторые имена. Имя состоит из двух частей: имени слева от пробела и фамилии справа от пробела, как показано ниже.
var users = {
values: ["Dean Edwards", "Alex Russell", "Dean Tom"]
};
Мы собираемся добавить метод поиска к объекту пользователей,
Когда никакие параметры не передаются, всеusers .values
;
При передаче параметра вернуть элемент, чье имя соответствует этому параметру;
При передаче двух параметров имя и фамилия сопоставляются и возвращаются.
В этом требовании метод поиска должен выполнять различные операции в зависимости от количества параметров.Затем мы добавляем метод поиска к объекту пользователей с помощью функции addMethod.
function addMethod (object, name, fn) {
// 先把原来的object[name] 方法,保存在old中
var old = object[name];
// 重新定义 object[name] 方法
object[name] = function () {
// 如果函数需要的参数 和 实际传入的参数 的个数相同,就直接调用fn
if (fn.length === arguments.length) {
return fn.apply(this, arguments);
// 如果不相同,判断old 是不是函数,
// 如果是就调用old,也就是刚才保存的 object[name] 方法
} else if (typeof old === "function") {
return old.apply(this, arguments);
}
}
}
функция addMethod, которая принимает 3 параметра
Первый: объект, чтобы связать метод, чтобы,
Второе: имя связанного метода,
Третье: методы, которые нужно связать
При оценке количества параметров функция addMethod не только использует объект arguments, но также использует свойство length функции.
Свойство length функции возвращает количество формальных параметров при определении функции.
Проще говоря, длина функции состоит в том, что функция требует несколько параметров, иarguments.length
Когда функция вызывается, она действительно передает функции несколько параметров
function fn (a, b) {
console.log(arguments.length)
}
console.log(fn.length); // 2
fn('a'); // 1
Далее мы используем эту функцию addMethod
// 不传参数时,返回整个values数组
function find0 () {
return this.values;
}
// 传一个参数时,返回firstName匹配的数组元素
function find1 (firstName) {
var ret = [];
for (var i = 0; i < this.values.length; i++) {
if (this.values[i].indexOf(firstName) === 0) {
ret.push(this.values[i
]);
}
}
return ret;
}
// 传两个参数时,返回firstName和lastName都匹配的数组元素
function find2 (firstName, lastName) {
var ret = [];
for (var i = 0; i < this.values.length; i++) {
if (this.values[i
] === (firstName + " " + lastName)) {
ret.push(this.values[i
]);
}
}
return ret;
}
// 给 users 对象添加处理 没有参数 的方法
addMethod(users, "find", find0);
// 给 users 对象添加处理 一个参数 的方法
addMethod(users, "find", find1);
// 给 users 对象添加处理 两个参数 的方法
addMethod(users, "find", find2);
// 测试:
console.log(users.find()); //["Dean Edwards", "Alex Russell", "Dean Tom"]
console.log(users.find("Dean")); //["Dean Edwards", "Dean Tom"]
console.log(users.find("Dean","Edwards")); //["Dean Edwards"]
Функция addMethod использует характеристики замыканий для подключения каждой функции через переменную old, чтобы все функции оставались в памяти.
Каждый раз, когда вызывается функция addMethod, создается old, формирующий замыкание.
мы можем пройтиconsole.dir(users.find)
, выведите метод find в консоль и посмотрите.
Приведенный выше пример является отцом jQuery.John Resigнаписано им в егоблоги его книгаСекреты JavaScript-ниндзяЭто было упомянуто в первом издании, а перегрузка функций также объясняется в главе 4 книги.Функция addMethod в тексте — это пример 4.15 в книге.Заинтересованные друзья могут пойти и посмотреть его.
Приведенные выше примеры, по сути, оценивают количество параметров и выполняют различные операции в соответствии с разными числами.Следующий пример заключается в выполнении различных операций путем оценки типа параметров.
Давайте посмотрим на jQuerycss() метод.
Метод css() возвращает или устанавливает одно или несколько свойств стиля соответствующего элемента.
css(name|pro|[,val|fn])
Мы видим, что метод css() имеет 5 параметров, 3 из которых являются одним параметром, а два других — двумя параметрами. В случае только одного параметра, если тип параметра является строкой или массивом, получается значение свойства, а если параметр является объектом, значение свойства устанавливается.
jQuerycss() методОн заключается в том, чтобы определить, какую операцию выполнять, исходя из типа параметра.
Давайте посмотрим на jQuery 3.3.1 висходный код
// name 表示属性名
// value 表示属性值
css: function( name, value ) {
return access( this, function( elem, name, value ) {
var styles, len,
map = {},
i = 0;
// 判断属性名是不是数组
// 是数组就遍历,调用jQuery.css 方法传入每个属性名,获取样式
if ( Array.isArray( name ) ) {
styles = getStyles( elem );
len = name.length;
for ( ; i < len; i++ ) {
map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
}
return map;
}
// 如果value 不等于 undefined 就调用jQuery.style 方法设置样式
// 如果value 等于 undefined 就调用jQuery.css 方法获取样式
return value !== undefined ?
jQuery.style( elem, name, value ) :
jQuery.css( elem, name );
}, name, value, arguments.length > 1 );
}
Метод css() использует три метода:
1. Метод jquery.access (), этот метод может получить или установить, один или несколько значений атрибутов
jQuery.access( )В методе есть что-то подобноекод
// 设置多个属性值
// 如果属性名(key)的类型是 object,就遍历这个对象
// 遍历一次就调用一次 access()方法,并传入这次的属性名和属性值
if ( jQuery.type( key ) === "object" ) {
chainable = true;
for ( i in key ) {
jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
}
// 设置一个值
} else if ( value !== undefined ) {
......
}
То есть этот метод помогает методу css() определить, является ли первый параметр строкой или объектом.
2. Метод jQuery.style(): чтение или установка атрибутов стиля в узлах DOM.
В методе css(), если передается второй параметр, то есть когда необходимо установить значение атрибута, будет вызван метод jQuery.style() для установки стиля
3. jQuery.css(): чтение значений стиля DOM для элементов DOM.
здесьjQuery.css( )черезjQuery.extend( )
Добавлен метод, о котором мы упоминали в началеcss() метод, черезjQuery.fn.extend( )
Добавлены методы, это не один и тот же метод.
Разница между jQuery.extend() и jQuery.fn.extend()
Функция jQuery.extend() предназначена для добавления метода класса (статического метода) в класс jQuery, который необходимо вызывать через класс jQuery (непосредственно с помощью $.xxx Call);
Функция jQuery.fn.extend() предназначена для добавления членов (методов экземпляра) в класс jQuery, и все экземпляры jQuery могут вызываться напрямую (необходимо вызывать с помощью $().xxx).
Преимущества перегрузки
Перегрузка — это на самом деле объединение нескольких функций с похожими функциями в одну функцию, а имя функции используется повторно. Если метод css() в jQuery не использует перегрузку, то для завершения функции должно быть 5 разных функций, тогда нам нужно запомнить 5 разных имен функций и количество параметров, соответствующих каждой функции И типу, что, очевидно, более хлопотно.
Суммировать
Хотя JavaScript на самом деле не имеет перегрузки, эффект перегрузки очень распространен в JavaScript, например, в массивах.метод splice(), один параметр может быть удален, два параметра могут быть удалены частично, три параметра могут быть удалены, а затем могут быть добавлены новые элементы.
Другой примерметод parseInt(), передавая один параметр, решается, следует ли использовать шестнадцатеричный синтаксический анализ или десятичный синтаксический анализ.Если переданы два параметра, второй параметр используется в качестве основы числа для синтаксического анализа.
Метод, упомянутый в статье для реализации эффекта перегрузки, по существу заключается в оценке параметров.Будь то оценка количества параметров или оценка типа параметров, он основан на различных параметрах, чтобы решить, какую операцию выполнять.
Хотя перегрузка может принести нам много удобства, ею нельзя злоупотреблять.Не объединяйте несколько принципиально не связанных между собой функций в одну функцию, это не имеет смысла.