{"id":22793094,"url":"https://github.com/kripod/tc39-proposal-private-function-arguments","last_synced_at":"2026-01-29T15:33:56.823Z","repository":{"id":81144887,"uuid":"235115658","full_name":"kripod/tc39-proposal-private-function-arguments","owner":"kripod","description":"Private function arguments for creating closures implicitly.","archived":false,"fork":false,"pushed_at":"2020-01-22T16:27:33.000Z","size":12,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-05-31T18:34:08.995Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kripod.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-01-20T14:07:27.000Z","updated_at":"2020-01-22T16:27:36.000Z","dependencies_parsed_at":null,"dependency_job_id":"8684de0e-ebed-47b7-ac2e-7a37eadc743a","html_url":"https://github.com/kripod/tc39-proposal-private-function-arguments","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/kripod/tc39-proposal-private-function-arguments","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kripod%2Ftc39-proposal-private-function-arguments","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kripod%2Ftc39-proposal-private-function-arguments/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kripod%2Ftc39-proposal-private-function-arguments/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kripod%2Ftc39-proposal-private-function-arguments/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kripod","download_url":"https://codeload.github.com/kripod/tc39-proposal-private-function-arguments/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kripod%2Ftc39-proposal-private-function-arguments/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28880240,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-29T10:31:27.438Z","status":"ssl_error","status_checked_at":"2026-01-29T10:31:01.017Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-12T03:18:01.025Z","updated_at":"2026-01-29T15:33:56.810Z","avatar_url":"https://github.com/kripod.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Private function arguments for JavaScript\n\nPrivate function arguments for creating closures implicitly.\n\n[Discussion on TC39 Discourse](https://es.discourse.group/t/private-function-arguments-for-creating-closures-implicitly/199)\n\n## Motivation\n\nTail recursive function parameters should be encapsulated in a closure to avoid modifying them from the outside. The following code demonstrates calculating the factorial of an integer:\n\n```js\nfunction fact(n) {\n  // A closure is defined explicitly to protect `acc` from unwanted modification\n  function fact_inner(n, acc) {\n    if (n \u003e 0) return fact_inner(n - 1, n * acc);\n    return acc;\n  }\n  return fact_inner(n, 1);\n}\n```\n\nWhile `fact` accounts for a simple mechanism, the explicit closure greatly increases the mental complexity of the code. As [private class fields](https://github.com/tc39/proposal-class-fields#private-fields) are already on the track of standardization, a similar syntax could be utilized for making function parameters inaccessible for callers:\n\n```js\n// From the outside, the function below only takes a single argument\nfunction fact(n, #acc = 1) {\n  if (n \u003e 0) return fact(n - 1, n * #acc);\n  return #acc;\n}\n```\n\nTransformation between the presented code snippets is possible with transpilers.\n\n## Details\n\n### Private arguments shall be specified after public ones\n\nPrivate arguments shall not be seen by callers. Extra parameters provided beyond the public ones shall be ignored. The value of private arguments may not be overrided from outside the scope of the function body. For example, calling `fact(3, 999, null)` should retain the value of `#acc = 1` by ignoring superfluous parameters.\n\nIn order to avoid confusion between the order of parameters, private arguments should be specified after their public counterparts:\n\n```js\n// The public method signature seen by callers is `fn(x, y)`\nfunction fn(x, y, #a = 0, #b) { /* ... */ }\n```\n\nPlease take note that private arguments act like syntactic sugar for defining a new closure with multiple outer variables.\n\n### Rest parameters may not be mixed with private arguments\n\n- Private rest parameters like `...#args` or `#...args` are out of consideration, as they provide no known value as accumulator variables. However, if a specific use-case was missed, please open a new issue regarding the case!\n\n- Concerns were [raised](https://github.com/kripod/tc39-proposal-private-function-arguments/issues/1) about compatibility with public rest parameters. Being the least confusing approach to date, private arguments shall not be allowed alongside rest parameters.\n\n### Default values for private arguments are mandatory\n\nAs [private arguments shall be specified after public ones](#private-arguments-shall-be-specified-after-public-ones), it would not make sense to allow private arguments without a default parameter, as the last public argument may also be optional.\n\n```js\nfunction fn1(x, y = 1, #a,     #b = 3) {} // Incorrect\nfunction fn2(x, y = 1, #a = 2, #b = 3) {} // Correct\n```\n\n### `arguments` are not modified\n\nTo retain backwards compatibility, the function-specific `arguments` object shall not include private arguments.\n\n### When transformed, the inner function should forward operations to the outer method\n\nAs observed in [issue #2](https://github.com/kripod/tc39-proposal-private-function-arguments/issues/2), the following code should always modify the outer function:\n\n```js\nfact.x = 'test';\nfunction fact(n, #acc = 1) {\n  if (n \u003e 0) return fact(n - 1, n * #acc);\n  console.log(fact.x); // 'test'\n  return #acc;\n}\n```\n\nHowever, a `Proxy` is required to bridge the gap between `fact_inner` and `fact.x` inside the function body:\n\n```js\nfunction fact(n) {\n  function fact_inner(n, acc) {\n    if (n \u003e 0) return fact_inner(n - 1, n * acc);\n    return acc;\n  }\n  const fact_inner_proxy = new Proxy(\n    fact_inner,\n    {\n      set(_obj, prop, value) {\n        fact[prop] = value;\n        return true;\n      },\n      get(_obj, prop) {\n        return fact[prop];\n      },\n      // Other traps may also be added\n    },\n  );\n  return fact_inner_proxy(n, 1);\n}\n```\n\n### Optimization opportunities for preprocessors\n\nBy detecting the operator usage sorrounding private arguments, a compiler may be able to optimize `const x = 20 * fact(3)` as follows:\n\n```js\nconst x = fact(3, 20);\n\nfunction fact(n, _acc) {\n  if (n \u003e 0) return fact(n - 1, n * _acc);\n  return _acc;\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkripod%2Ftc39-proposal-private-function-arguments","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkripod%2Ftc39-proposal-private-function-arguments","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkripod%2Ftc39-proposal-private-function-arguments/lists"}