Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   функция позволяющая фиксировать все аргументы (https://javascript.ru/forum/misc/71489-funkciya-pozvolyayushhaya-fiksirovat-vse-argumenty.html)

ami_moor 22.11.2017 18:14

функция позволяющая фиксировать все аргументы
 
Задача взята с http://dkab.github.io/jasmine-tests/?spec=6

Суть: Написать функцию partialAny которая позволяет фиксировать зафиксировать любые аргументы, пропущенные аргументы обозначаются с помощью undefined:

Написала cследующее, но не прошла тестировку, выдаёт следующее "может вызываться несколько раз и результаты во второй раз не зависят от первого" направьте меня как переписать правильно..:
function partialAny() {
	var func = arguments[0];

	var masArg = [];
	var masArg2 = [];
	var count = 0;
	for(let k=1; k<arguments.length; k++) {
		masArg[k-1] = arguments[k];
	}
	return function() {
		for(let k=0; k<arguments.length; k++) {
			masArg2[k] = arguments[k];
		}
		for(let z=0; z<masArg.length; z++) {

			if(masArg[z] === undefined) {
			
				masArg[z] = masArg2[count];
				count++;
			}
		}
		for(let z=count; z<masArg2.length; z++) {
			masArg[masArg.length] = masArg2[z];
		}
		return func.apply(this, masArg);
	}
}

function test(a, b, c) { return "a=" + a + ", b=" + b + ", c=" +  c}
var test1_3 = partialAny(test, 1, undefined, 3, undefined);
console.log(test1_3(5, 9, 22, "asdasd")); // a=1,b=5,c=3
console.log(test1_3(1, 2, 4, "7")); // должна вывести a=1,b=2,c=3   а выводит a=1,b=5,c=3 (т.е предыдущее значение)

Nexus 23.11.2017 10:16

ami_moor, не знаю правильно ли я понял суть задачи, но:
function test(a, b, c) { return 'a=' + a + ',b=' + b + ',c=' + c; }
var _test=partialAny(test,1,undefined,3,undefined);
console.log(_test(5, 9, 22, "asdasd"));
console.log(_test(1, 2, 4, "7"));


function partialAny(callable,_args){
	if(!arguments.length)
		throw new Error('Missing first argument');

	var args=[];
	for(var i=0;i<arguments.length;i++){
		args[i]=arguments[i];
	};
	
	callable=args.shift();
	
	if(typeof callable!='function')
		throw new Error('First argument must be function');
		
	return function(){
		var _args=args.slice(0);
		
		if(!!arguments.length){
			var blanks=[];
			for(var i=0;i<_args.length;i++){
				if(_args[i]===undefined)
					blanks.push(i);
			};
			
			for(i=0;i<arguments.length;i++){
				var key=blanks.shift();
				if(key!==undefined)
					_args[key]=arguments[i];
				else
					_args.push(arguments[i]);
			};
		};
		
		return callable.apply(window,_args);
	};
};

jerseybb 23.11.2017 10:48

function partialAny(fn, ...args) {
    return (...args2) => {
      return fn(...args.map(arg => arg === undefined ? args2.shift() : arg), ...args2)
    }
}

Принцип, если непонятен синтаксис:
1. Проходимся по массиву аргументов функции partialAny и возвращаем новый массив (Array.map)
2. Сравниваем каждый элемент с undefined
3. Если true, заменяем первым элементом из массива аргументов возвращаемой функции (с удалением, Array.shift)
4. Вызываем переданную функцию fn с аргументами из получившегося массива (пункт 1) аргументов, добавляем в конец оставшиеся аргументы из массива аргументов возвращаемой функции (... - оператор spread)

рони 23.11.2017 11:49

Цитата:

Сообщение от ami_moor
должна вывести a=1,b=2,c=3

a=1,b=1,c=3 :-?

рони 23.11.2017 11:51

ami_moor,
function partialAny() {
    var c = arguments[0],
        d = [].slice.call(arguments, 1),
        a;
    return function() {
        var e = 0;
        a = [].slice.call(arguments, 0);
        a = d.map(function(b) {
            return void 0 === b ? a[e++] : b
        });
        return c.apply(this, a)
    }
};

function test(a, b, c) { return "a=" + a + ", b=" + b + ", c=" +  c}
var test1_3 = partialAny(test, 1, undefined, 3, undefined);
console.log(test1_3(5, 9, 22, "asdasd")); // a=1,b=5,c=3
console.log(test1_3(1, 2, 4, "7")); //  a=1,b=1,c=3

jerseybb 23.11.2017 12:20

ami_moor, Ваша ключевая ошибка в том, что результат возвращаемой функции зависит от переменных, которые хранятся в замыкании и которые Вы изменяете:

1. В возвращаемой функции Вы вызываете func с массивом аргументов masArg, который изменили до этого. Чего делать нельзя, так как при последующем вызове функции массив masArg сохранится в замыкании. Перед изменением masArg сделайте копию массива и работайте с ней. К примеру:
let args = masArg.slice()

2. Во вторых, у Вас в замыкании хранится count и в возвращаемой функции эта переменная никак не обновляется. Значит при повторном вызове она будет иметь значение на конец предыдущего вызова функции.

Для исправления Вашего кода вынесите объявление masArg2 и count в начало возвращаемой функции. И перед проверкой на undefined сделайте копию masArg и вносите аргументы уже в копию, аргументы из которой потом передадите в func.

Ну и конечно, как уже сказал рони, результат второго вызова должен быть не 'a=1, b=2, c=3', а 'a=1, b=1, c=3'.


Часовой пояс GMT +3, время: 09:37.