{"id":40702295,"url":"https://github.com/sourcevault/lazybindall","last_synced_at":"2026-01-21T12:06:13.166Z","repository":{"id":57154643,"uuid":"121100061","full_name":"sourcevault/lazybindall","owner":"sourcevault","description":"like bindall but lazy - meaning closures get created when needed. ","archived":false,"fork":false,"pushed_at":"2018-02-22T18:12:43.000Z","size":276,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-02T11:14:07.304Z","etag":null,"topics":["functional-programming","javascript","livescript","mostjs"],"latest_commit_sha":null,"homepage":null,"language":"LiveScript","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/sourcevault.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-02-11T08:00:00.000Z","updated_at":"2022-11-27T03:03:02.000Z","dependencies_parsed_at":"2022-09-06T19:21:34.132Z","dependency_job_id":null,"html_url":"https://github.com/sourcevault/lazybindall","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sourcevault/lazybindall","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcevault%2Flazybindall","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcevault%2Flazybindall/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcevault%2Flazybindall/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcevault%2Flazybindall/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sourcevault","download_url":"https://codeload.github.com/sourcevault/lazybindall/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sourcevault%2Flazybindall/sbom","scorecard":{"id":839478,"data":{"date":"2022-08-15","repo":{"name":"github.com/sourcevault/lazybindall","commit":"e2be44fa7757f81734fbe982d888622027ce1f95"},"scorecard":{"version":"v4.5.0-26-g10b6052","commit":"10b6052acfb4f0b8136bc4876cb6f5b6f26bfe93"},"score":4.8,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) out of 15 and 0 issue activity out of 0 found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/10b6052acfb4f0b8136bc4876cb6f5b6f26bfe93/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"no reviews found","details":["Warn: no reviews found for commit: e2be44fa7757f81734fbe982d888622027ce1f95","Warn: no reviews found for commit: de3d4f5b5e581ce903eb9d3555673c7408508f11","Warn: no reviews found for commit: 3fb7ed5ab5490d9e20fa1a70d2d4e643969b2574","Warn: no reviews found for commit: 283045bd824d7273e8fd3727de352bf65b051ba8","Warn: no reviews found for commit: c161c38bdc857f3bd61d25fe6751184480e97bd3","Warn: no reviews found for commit: 51065453edccd035417bd37ad470268dc812dbca","Warn: no reviews found for commit: 20d7f0711bd5375510406b94e3b17ed01c2a2f87","Warn: no reviews found for commit: 1f74a84999cb233f6d1fd0be9791f66422aaf328","Warn: no reviews found for commit: def4aee36369ed8b1c469f16af3f15c9999e1e29","Warn: no reviews found for commit: a35b9dca2e17d9d2b87fdb5f9a0d3b34b5a2969f","Warn: no reviews found for commit: b12f7695d386252601c180e00fa4f482b00cbfb6","Warn: no reviews found for commit: b8708d074c5f926fc5c1d8f28e8c3dbde26f72e8","Warn: no reviews found for commit: 3736bee46c51ef8bb75114faca32180537305fbe","Warn: no reviews found for commit: 9aaf6e03350e33c9cd8798d66bad1fd4b2527bf0","Warn: no reviews found for commit: 244830800a3f185a604f716253170c7c0cd06e43"],"documentation":{"short":"Determines if the project requires code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/10b6052acfb4f0b8136bc4876cb6f5b6f26bfe93/docs/checks.md#code-review"}},{"name":"CII-Best-Practices","score":0,"reason":"no badge detected","details":null,"documentation":{"short":"Determines if the project has a CII Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/10b6052acfb4f0b8136bc4876cb6f5b6f26bfe93/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":10,"reason":"all dependencies are pinned","details":["Info: GitHub-owned GitHubActions are pinned","Info: Third-party GitHubActions are pinned","Info: Dockerfile dependencies are pinned","Info: no insecure (not pinned by hash) dependency downloads found in Dockerfiles","Info: no insecure (not pinned by hash) dependency downloads found in shell scripts"],"documentation":{"short":"Determines if the project has declared and pinned its dependencies.","url":"https://github.com/ossf/scorecard/blob/10b6052acfb4f0b8136bc4876cb6f5b6f26bfe93/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":10,"reason":"tokens are read-only in GitHub workflows","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/10b6052acfb4f0b8136bc4876cb6f5b6f26bfe93/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/10b6052acfb4f0b8136bc4876cb6f5b6f26bfe93/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"no published package detected","details":["Warn: no GitHub publishing workflow detected"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/10b6052acfb4f0b8136bc4876cb6f5b6f26bfe93/docs/checks.md#packaging"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: : LICENCE:1"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/10b6052acfb4f0b8136bc4876cb6f5b6f26bfe93/docs/checks.md#license"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/10b6052acfb4f0b8136bc4876cb6f5b6f26bfe93/docs/checks.md#binary-artifacts"}},{"name":"Vulnerabilities","score":10,"reason":"no vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/10b6052acfb4f0b8136bc4876cb6f5b6f26bfe93/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":null,"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/10b6052acfb4f0b8136bc4876cb6f5b6f26bfe93/docs/checks.md#security-policy"}},{"name":"Dependency-Update-Tool","score":0,"reason":"no update tool detected","details":["Warn: dependabot config file not detected in source location.\n\t\t\tWe recommend setting this configuration in code so it can be easily verified by others.","Warn: renovatebot config file not detected in source location.\n\t\t\tWe recommend setting this configuration in code so it can be easily verified by others."],"documentation":{"short":"Determines if the project uses a dependency update tool.","url":"https://github.com/ossf/scorecard/blob/10b6052acfb4f0b8136bc4876cb6f5b6f26bfe93/docs/checks.md#dependency-update-tool"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":["Warn: no GitHub releases found"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/10b6052acfb4f0b8136bc4876cb6f5b6f26bfe93/docs/checks.md#signed-releases"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":null,"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/10b6052acfb4f0b8136bc4876cb6f5b6f26bfe93/docs/checks.md#fuzzing"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/10b6052acfb4f0b8136bc4876cb6f5b6f26bfe93/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-23T20:06:01.684Z","repository_id":57154643,"created_at":"2025-08-23T20:06:01.684Z","updated_at":"2025-08-23T20:06:01.684Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28632781,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T04:47:28.174Z","status":"ssl_error","status_checked_at":"2026-01-21T04:47:22.943Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5: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":["functional-programming","javascript","livescript","mostjs"],"created_at":"2026-01-21T12:06:12.495Z","updated_at":"2026-01-21T12:06:13.161Z","avatar_url":"https://github.com/sourcevault.png","language":"LiveScript","readme":"[![Build Status](https://travis-ci.org/sourcevault/lazybindall.svg?branch=master)](https://travis-ci.org/sourcevault/lazybindall)\n\n![](images/logo.jpg)\n\n**Install Using Any ..**\n```\n- npm install lazybindall\n\n- npm install sourcevault/lazybindall\n\n- npm install gitlabs:ourcevault/lazybindall\n\n- npm install @sourcevault/lazybindall\n```\n\n**Type Signature**\n\n```haskell\nlazybindall  :: ( ob , methds ) -\u003e obmethds\n``` \n\n-  `ob \u003cObject\u003e`  -  Methods in `methds` get bound to `ob`.\n\n-  `methds \u003cObject\u003e` - Object with props *that are methods* that we want to lock to `ob`\n\n- `obmethds \u003cObject\u003e` is an object whose props are defined be `methds` and have there context locked to `ob`.\n\n**Simple Example**\n\n```javascript\n\nvar foo = {name:\"sourcevault\"}\n\nvar methds = \n  {\n    show:function()\n    {\n      console.log (this)\n    }\n  }\n\n// ----------------------------------------------\n\nvar lazybindall = require (\"lazybindall\")\n\nvar bound = lazybindall ( foo , methds )\n\nbound.show() // {name:\"sourcevault\"}\n\n```\n\n\n## Let Me Explain ..\n\n### Relevant Background\n\nLocking context in Javascript can **only** happen through closures:\n\n```javascript\n\nvar foo = function (x)\n{\n  this.value += x \n}\n\nlockFoo = function (state) // \u003c- state is captured in the inner function\n{\n  return function (x) \n  {\n    foo.call (state,x) // state gets captured from the outer function \n  }\n}  \n\nstate = {value:1}\n\nlockedFoo = lockFoo (state) \n\nlockedFoo(3)\n\nconsole.log (state) // {value:4}\n\n```\n\nThe functionality expressed above is well encapculated in the `.bind` method that every function in javascript can call upon to lock context.\n\nWe can use `bind`  to create `bindall` which is just a for loop for applying bind for multiple functions.\n\nThe usecase for `bindall` is apparent when large number of methods with  internal state dependency require exporting. The issue arises due to the consumer having liberty to attach any exported function to external objects causing **mutation** to the internal `.this` variable - breaking any internal code that depends on `.this` staying invariant.\n\n```javascript\n\n// ./largeApi.js\n\n// What a potential large API surface looks like \n\nOb = function()\n{\n  this.resultList = [] \n\n  return (this)\n}\n\nOb.prototype.f1 = function()\n{\n  var sum = 0\n  // .... /\n  this.resultList.push( sum )\n  // .... /\n  return (this)\n}\n\nOb.prototype.f2 = function(){// .... /}\n\nOb.prototype.f3 = function(){// .... /}\n\n  // .... /\n  // .... /\n  // .... /\n\nOb.prototype.f100 = function(){// .... /}\n\nmodule.exports = Ob\n\n```\n\n\n\n\n```javascript\n\n// test.js\n\nvar api = require (\"./largeApi\")\n\nvar _ = require (\"underscore\")\n\nvar instance = new api()\n\nvar boundApi = _.bindAll(instance)\n\nsetTimeout (boundApi.f1,1000) // [1] runs fine \n\nsetTimeout (instance.f1,1000) \n\n// [2] TypeError: Cannot read property 'push' of undefined\n\n// [2] ofcourse V8 vomited an error since .this of api.f1 points to global \n\n\n```\n\n**ADDITIONAL  READING:**\n\n\n- `underscore.js`'s [original implementation](https://github.com/jashkenas/underscore/blob/5c237a7c682fb68fd5378203f0bf22dce1624854/underscore.js#L799-L807) of `bindall`. \n\n- Michael Fogus's book [\"*Introducting Functional Programming with Underscore.js*\"](http://shop.oreilly.com/product/0636920028857.do) has more details involing functional design patterns invovling `bindall`. \n\n- [Here is my take](https://github.com/sourcevault/bindall) on `bindall`  \n\n### Why Be Lazy ?\n\nUsing `bindall` is perfectly fine for most application but pay attention to what happens at the margins. `bindall` is making a copy of the data structure representing our module. If Fig 1 is the data structure showing our module, then `bindall` is making a modified copy  (copy not shown in Fig 1).\n\n![](images/single.jpg)\n**Fig 1** is a graphical representation of the data structure of large exported module with internal state stored in an object.\n\nThe inefficiency in constantly making clones becomes more apparent when we consider the fact that the consumer might be interested in making *n* instances each attached to some unique object (Fig 2).\n\n![](images/many.jpg)\n**Fig 2** - *n* instances with **unique** object (state) for each instance. \n(`bindall` clone not shown)\n\nIt's not difficult to see how applying `bindall` to each module layer could quickly cause memory issues. APIs involving the DOM have large surface area for **each** document object\n(ie. onclick, onhover, onmouseover ...).\n\nThere is something we notice when handling large APIs, that can give us a clue as to how we can optimize - we *rarely* use **all** possible methods for each instance (Fig 3). The reason we expose large API surfaces is to expose all **possible** functionalities, so that it works under varied use, even as creator we do not expect complete method utilization at every use - this is where it pays to be lazy. \n\n![](images/many2.jpg)\n**Fig 3** - In practice most methods calls will be sparsely distributed - `bindall` makes more sense for small APIs with dense use, while lazy binding allocates memory only when required.\n\nWhat we could do instead of an eagar `bindall` is to only `bind` when our function leaves the comfort of its parent object. \n\nWe can do this by taking advantage of ES6 proxy getter hooks to lock context - instead of retroactively binding and **then** exporting it.\n\n### Benchmark \n\n*...for 10,000 object with 9 methods*\n\n|   Method         | Total Memory (MB) | Time (millisecond)  |\n|:----------------:|------------------:|--------------------:|\n|     `.prototype` |                  6|                   31|\n| lazy  closure    |                  9|                   54|\n| eagar closure    |                 49|                6,172|\n\n**NOTES:**\n- will be interesting to see how benchmark values change against *increasing* number of methods.\n\n- `.prototype` is always going to be fastest because there is **no** closure creation - so state cannot be even passed to the event loop. It helps create a lower bound.\n\n- Time and memory is related for our benchmark since we are are keeping CPU intensive tasks constant, hence it can be assumed that time is a reflection of how long it takes the system to allocate memory, giving eagar closures *both* a memory, and time penalty.\n\n- benchmark source is `src/benchmark.ls`, run using `node dist/benchmark.js`\n\n- hardware used - `i7-3667U CPU (2 GHz 2.5 GHz), (x64, 7.86 RAM)`\n\n\n### TODO\n\n- More user friendly API simarly to `sourcevault/bindall`\n\n- `most.js` integration\n\n### Updates and API change\n\n- Initial `0.0.1` release with a single exported function.\n\n## License\n \n- Code released under MIT Licence, see [LICENSE](https://github.com/sourcevault/lazybindall/blob/master/LICENCE) for details.\n\n- Documentation and Images released using CC-BY-4.0 see [LICENSE](https://github.com/sourcevault/lazybindall/blob/master/images/LICENCE) for details.\n\n\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsourcevault%2Flazybindall","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsourcevault%2Flazybindall","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsourcevault%2Flazybindall/lists"}