首页 > 解决方案 > How do I refer to arguments of a function when the function is passed in as a parameter?

问题描述

New to JavaScript, so give me some leeway.

I'm currently trying to simulate contracts in JavaScript. There are preconditions and postconditions which can be defined when you declare a function. I've compiled a simple setup of how it should work below.

Function mult() has a few contracts which should check if the two inputs are numbers and should check if the resulting output is also a number.

//CONTRACT
function isNumber(v) {
  return !Number.isNaN(v) && typeof v === 'number';
}
isNumber.expected = "number";

/**
 * @param preList Array of contracts to check
 * @param post Expected result type as a contract
 * @param f the function
 */
function contract (preList, post, f) {
    //??? No idea
    //precondition
    for (let i = 0; i < preList.length; i++) {  //THIS DOESNT WORK
        let valid = preList[i].call(this, f.arguments[i]);
        if (valid === false) throw "caller's fault";
    }
    //postcondition
    let result = f.call(this, f.arguments);
    if ((post.call(this, result)) === false) throw "library's fault";
}

//EXAMPLE

var mult = contract(
  [isNumber, isNumber],
  isNumber,
  function mult (x, y) {
    return x*y;
  });

//TEST CODE

console.log("First test")
console.log(mult(3, 4));
console.log();

console.log("Second test")
try {
  console.log(mult(3, "four"));
} catch (e) {
  console.log(e.message);
}
console.log();

I'm fairly sure a lot of the contract(){} function is wrong and after a lot of trial and error I have ended up here.

Currently I'm trying to loop through all the preconditions and call them with the arguments of f. From my understanding, (arguments) refers to the arguments of the current function, but I'm looking for the arguments of f, not of contract. f.arguments

I've also tried to do this with JavaScript proxies which can intercept function calls by setting traps for apply and construct but have gotten stuck as well.

Any help and pointers would be greatly appreciated. Using node.js to run this program.

标签: javascript

解决方案


你可以尝试这样的事情:

"use strict";

function isNumber(v) {
  return !Number.isNaN(v) && typeof v === "number";
}

/**
 * @param preList Array of contracts to check
 * @param post Expected result type as a contract
 * @param f the function
 * @param array: arguments passed to function f
 */

function contract(preList, post, f, args) {
  for (let i = 0; i < preList.length; i++) {
    let valid = preList[i].call(this, args[i]);
    if (valid === false) throw "caller's fault";
  }
  let result = f.apply(this, args);
  if (post.call(this, result) === false) throw "library's fault";
  return result;
}

let mult = function(x, y) {
  let f = function(x, y) {
    return x * y;
  };
  return contract([isNumber, isNumber], isNumber, f, arguments);
};

console.log("First test");
console.log(mult(3, 4));  // 12

console.log("Second test");
try {
  console.log(mult(3, "four"));
} catch (e) {
  console.log(e); // caller's fault
}


推荐阅读