{
    "version": "https://jsonfeed.org/version/1",
    "title": "JavaScript",
    "home_page_url": "https://onp4.com/@vadim/~js",
    "description": "JavaScript",
    "author": {
        "name": "Vadim Dalecky",
        "url": "https://onp4.com/@vadim"
    },
    "items": [
        {
            "id": "https://onp4.com/@vadim/p/ut31o77l9x",
            "content_html": "Modern eval\n\n```js\nconst js = `console.log('Hello everyone!');`;\nconst encodedJs = encodeURIComponent(js);\nconst dataUri = 'data:text/javascript,'+ encodedJs;\nimport(dataUri);\n```",
            "url": "https://onp4.com/@vadim/p/ut31o77l9x",
            "date_modified": "2025-10-19T22:38:04.264Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/0ic41fxln8",
            "content_html": "Claude Sonnet 4.0",
            "url": "https://onp4.com/@vadim/p/0ic41fxln8",
            "date_modified": "2025-08-29T09:39:27.102Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/tqziv1amkg",
            "content_html": "How to add code block in constructor before `super()` call? Wrap it in IIFE:\n\n```ts\nclass A extends B {\n  constructor () {\n    super((() => {\n       // Code block ...\n    })());\n  }\n}\n```",
            "url": "https://onp4.com/@vadim/p/tqziv1amkg",
            "date_modified": "2025-07-30T08:41:44.411Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/97awamfsgw",
            "content_html": "On TypeScript object types:\n\n- `{}` is a type which specifies that the value supports property access dot `.` operator. Like `(123 as {}).toString()`.\n- `object` (with lower case) specifies any non primitive value, such as object, array, function, etc.\n- `Object` (with upper case) specifies the type of the JavaScript built-in `Object` value.",
            "url": "https://onp4.com/@vadim/p/97awamfsgw",
            "date_modified": "2025-07-11T18:36:25.200Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/01h774oe2i",
            "content_html": "",
            "url": "https://onp4.com/@vadim/p/01h774oe2i",
            "date_modified": "2025-06-16T09:53:36.707Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/swwz2wfdj3",
            "content_html": "There has not been that many exciting new features in JavaScript last few years, but most recently it has changed. The FileSystem API in browser now allows website to access user's native file system. The Observable API will finally bring `Observable` natively into JavaScript, which is by far the best state management solution for UI's and handy for many other things. And most importantly, the *struct* API will be a huge game changer, the struct API will allow to create C-like structs in JavaScript, which will also be sharable across threads. This will enable effecting shared-memory parallel programming in JavaScript, which was not possible so far and has forced so many projects and developers pick Go or Rust, instead.",
            "url": "https://onp4.com/@vadim/p/swwz2wfdj3",
            "date_modified": "2025-03-19T18:32:08.218Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/lly1bbudbd",
            "content_html": "Debugging HTML/CSS of 3rd party website:\n\n```javascript\nsetInterval(() =>\n  [...document.querySelectorAll('*')]\n    .forEach(e => e.style.outline = '1px dotted red')\n  , 1000)\n```\n",
            "url": "https://onp4.com/@vadim/p/lly1bbudbd",
            "date_modified": "2024-11-16T21:52:29.502Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/20266uv7pf",
            "content_html": "Scopes in classes:\n\n```js\nclass A {\n  {\n    let cnt = 0;\n    \n    getCnt() {\n      return cnt;\n    }\n    \n    setCnt(val) {\n      cnt = val;\n    }\n  }\n}\n```\n\nWould be equivalent to scopes in prototype-based inheritance:\n\n```js\nfunction A() {}\n\n{\n  let cnt = 0;\n\n  A.prototype.getCnt = function() {\n    return cnt;\n  };\n  \n  A.prototype.setCnt = function(val) {\n    cnt = val;\n  };\n}\n```\n",
            "url": "https://onp4.com/@vadim/p/20266uv7pf",
            "date_modified": "2024-10-23T13:25:57.186Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/kl0ses006y",
            "content_html": "Publish to NPM any PR:\n\nhttps://github.com/stackblitz-labs/pkg.pr.new\n",
            "url": "https://onp4.com/@vadim/p/kl0ses006y",
            "date_modified": "2024-10-08T18:07:26.449Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/rnp76a72lm",
            "content_html": "# Zero-overhead Async/Await\n\n[Callbacks are significantly faster](https://hackernoon.com/nodejs-48x-faster-if-you-go-back-to-callbacks) than `Promise`s in Node.js. How can we get the performance of callbacks while benefiting from the `Promise` and async/await syntax?\n\nJavaScript could introduce *CallbackAwaitExpression*, which syntactically would look very much like the existing *AwaitExpression* but it would operate on top of callbacks instead of promises.\n\nThe callbacks would have the following form:\n\n```ts\ntype Callback<V, E = unknown> =\n  | (error: E) => void;\n  | (error: void, value: V) => void;\n```\n\nThe new *CallbackAwaitExpression* would have an extra **identifier** parameter of type `Callback`, syntactically in between the `await` keyword and the expression being awaited, for example, note the `cb` identifier:\n\n```js\nawait cb fs.readFile('myfile.txt', 'utf-8', cb);\n```\n\nLikewise, the async function syntax would also be extended to allow *AsyncCallbackFunction* type. There as well, the syntax would allow a single callback identifier:\n\n```js\nasync cb function(args, cb) {\n  // ...\n}\n```\n\nPutting this all together, this would allow to write async/await syntax-powered code, while benefiting from the performance of callbacks. It would allow to write code like this:\n\n```js\nasync _ function getFileData(filename, _) {\n  try {\n    const data = await _ fs.readFile('myfile.txt', 'utf-8', _);\n    return 'mydata: ' + data;\n  } catch (error) {\n    if (!!error && typeof error === 'object' && error.code === 'ENOENT') {\n      throw new Error('not found');\n    }\n    throw error;\n  }\n}\n```\n\nThe code would be equivalent to the existing JavaScript:\n\n```js\nfunction getFileData(filename, callback) {\n  const onCatch = (error) => {\n    if (!!error && typeof error === 'object' && error.code === 'ENOENT') {\n      callback(new Error('not found'));\n    } else {\n      callback(error);\n    }\n  };\n  try {\n    fs.readFile('myfile.txt', 'utf-8', (err, data) => {\n      if (err) {\n        onCatch(err);\n      } else {\n        try {\n          callback(null, 'mydata: ' + data);\n        } catch (error) {\n          onCatch(error);\n        }\n      }\n    });\n  } catch (error) {\n    onCatch(error);\n  }\n}\n```\n\nHere is how the above code can look like using the existing async/await syntax. The code is almost equivalent to the *async/await callback* proposal, but less performant due to `Promise` usage.\n\n```js\nasync function getFileDataAsync(filename) {\n    try {\n    const data = await promisify(fs.readFile)('myfile.txt', 'utf-8');\n    return 'mydata: ' + data;\n  } catch (error) {\n    if (!!error && typeof error === 'object' && error.code === 'ENOENT') {\n      throw new Error('not found');\n    }\n    throw error;\n  }\n}\n```\n\nOr, equivalently, the good old `promisify` utility could convert our callback powered function to this `Promise` powered one:\n\n```js\nconst getFileDataAsync = promisify(getFileData);\n```\n\n## Sugar Syntax\n\nWhen awaiting one can explicitly specify the callback identifier and explicitly use it as an argument:\n\n```js\nawait myCallback fs.readFile('a.txt', myCallback)\n```\n\nIf the await identifier `myCallback` is not used, it is automatically inserted in the function call as the last argument:\n\n```js\nawait _ fs.readFile('a.txt')\n```\n\nWhen defining an async callback function, the above text proposed to explicitly specify the callback identifier, like so:\n\n```js\nasync myCallback function getData(filename, myCallback) {}\n```\n\nInstead it can be reduced by simply using the `async` keyword once, in place of some argument:\n\n```js\nfunction getData(filename, async) {}\n```\n\nThe above syntax modifications reduce the example `getFileData` function to the following:\n\n```js\nfunction getFileData(filename, async) {\n  try {\n    const data = await _ fs.readFile('myfile.txt', 'utf-8');\n    return 'mydata: ' + data;\n  } catch (error) {\n    // ...\n  }\n}\n```\n\n## Using with TypeScript\n\nFrom the point of view of TypeScript, to define a new async callback function, one can simply use the `CallbackType`:\n\n```ts\ntype GetFileData = (filename: string, callback: Callback<string>) => void;\n```\n\nAlternatively, the `async` type shorthand could be introduced, to make it more explicit:\n\n```ts\ntype GetFileData = (filename: string, async<string>) => void;\n```\n\nMaybe it could be called `callback`:\n\n```ts\ntype GetFileData = (filename: string, callback<string>) => void;\n```\n",
            "url": "https://onp4.com/@vadim/p/rnp76a72lm",
            "date_modified": "2024-08-23T13:20:23.227Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/gqrahqqvms",
            "content_html": "[Callbacks are significantly faster](https://hackernoon.com/nodejs-48x-faster-if-you-go-back-to-callbacks) than `Promise`s in Node.js. How can we get the performance of callbacks while benefiting from the `Promise` and async/await syntax?\n\nJavaScript could introduce *CallbackAwaitExpression*, which syntactically would look very much like the existing *AwaitExpression* but it would operate on top of callbacks instead of promises.\n\nThe callbacks would have the following form:\n\n```ts\ntype Callback<V, E = unknown> = ErrorCallback<E> | ValueCallback<V>;\ntype ErrorCallback<E = unknown> = (error: E) => void;\ntype ValueCallback<V> = (error: void, value: V) => void;\n```\n\nThe new *CallbackAwaitExpression* would have an extra **identifier** parameter of type `Callback`, syntactically in between the `await` keyword and the expression being awaited, for example, note the `cb` identifier:\n\n```js\nawait cb fs.readFile('myfile.txt', 'utf-8', cb);\n```\n\nLikewise, the async function syntax would also be extended allow *AsyncCallbackFunction* type. There as well, the syntax would allow a single callback identifier:\n\n```js\nasync cb function(args, cb) {\n  // ...\n}\n```\n\nPutting this all together, this would allow to write async/await syntax-powered code, while benefiting from the performance of callbacks. It would allow to write functions like:\n\n```js\nasync _ function getFileData(filename, _) {\n  try {\n    const data = await _ fs.readFile('myfile.txt', 'utf-8', _);\n    return 'mydata: ' + data;\n  } catch (error) {\n    if (!!error && typeof error === 'object' && error.code === 'ENOENT') {\n      throw new Error('not found');\n    }\n    throw error;\n  }\n}\n```\n\nThe code would be equivalent to the existing JavaScript:\n\n```js\nfunction getFileData(filename, callback) {\n  const onCatch = (error) => {\n    if (!!error && typeof error === 'object' && error.code === 'ENOENT') {\n      callback(new Error('not found'));\n    }\n    callback(error);\n  };\n  try {\n    fs.readFile('myfile.txt', 'utf-8', (err, data) => {\n      if (err) return onCatch(err);\n      callback(null, 'mydata: ' + data);\n    });\n  } catch (error) {\n    onCatch(error);\n  }\n}\n```\n\nHere is how the above code can look like using the existing async/await syntax. The code is almost equivalent to the *async/await callback* proposal, but less performant due to `Promise` usage.\n\n```js\nasync function getFileData(filename) {\n    try {\n    const data = await promisify(fs.readFile('myfile.txt', 'utf-8'));\n    return 'mydata: ' + data;\n  } catch (error) {\n    if (!!error && typeof error === 'object' && error.code === 'ENOENT') {\n      throw new Error('not found');\n    }\n    throw error;\n  }\n}\n```",
            "url": "https://onp4.com/@vadim/p/gqrahqqvms",
            "date_modified": "2024-08-18T08:51:39.450Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/857h4ap4ls",
            "content_html": "https://blog.isquaredsoftware.com/2021/01/context-redux-differences/",
            "url": "https://onp4.com/@vadim/p/857h4ap4ls",
            "date_modified": "2024-08-08T19:07:09.038Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/ehvyvq5g6w",
            "content_html": "Parser CST-to-AST node transformation using JSON Expressions:\n\n```js\n['set', 'type', 'Number', {}]\n\n['apply', {\n  type: 'Number',\n  pos: ['$', '/csr/pos'],\n  end: ['$', '/csr/end'],\n  value: ['num', '/csr/text'],\n}, {}]\n\n['apply', {\n  value: ['num', '/csr/text'],\n}, ['$', '/ast']]\n\n['assign', ['$', '/ast'], {\n  value: ['num', '/csr/text'],\n}]\n\n['extend', ['$', '/ast'], {\n  '/value': ['num', ['$', '/csr/text']],\n}]\n\n\n['apply', ['$', '/ast'],\n  '/value', ['num', ['$', '/csr/text']],\n  '/isFloat', false,\n]\n\n['add', ['$', '/ast'],\n  '/value', ['num', ['$', '/csr/text']],\n  '/isFloat', false,\n]\n\n['$', '/ast/children/0']\n\n['o.set', {},\n  'value', ['num', ['$', '/csr/text']],\n  'location', ['o.set', {},\n    'start', ['$', '/csr/pos'],\n    'length', ['-', ['$', '/csr/end'], ['$', '/csr/pos']]\n  ],\n]\n```",
            "url": "https://onp4.com/@vadim/p/ehvyvq5g6w",
            "date_modified": "2024-06-16T22:14:34.730Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/0pshojgkpq",
            "content_html": "*Internalized* strings in V8 runtime are an immutable string collection in a common shared pool. Normally those are the strings known at the build time.",
            "url": "https://onp4.com/@vadim/p/0pshojgkpq",
            "date_modified": "2024-06-14T12:02:16.195Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/eaw42510se",
            "content_html": "You can internalize stings in V8 using `eval`:\n\n```js\ns = eval(JSON.stringify(s));\n```",
            "url": "https://onp4.com/@vadim/p/eaw42510se",
            "date_modified": "2024-06-14T12:01:27.029Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/vxuibqku5g",
            "content_html": "https://www.youtube.com/watch?v=U6s2pdxebSo",
            "url": "https://onp4.com/@vadim/p/vxuibqku5g",
            "date_modified": "2024-05-13T22:18:54.637Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/dqnx8upmvk",
            "content_html": "https://www.youtube.com/watch?v=5AqbCQuK0gM",
            "url": "https://onp4.com/@vadim/p/dqnx8upmvk",
            "date_modified": "2024-05-13T22:18:43.658Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/7ie0x9pzmm",
            "content_html": "",
            "url": "https://onp4.com/@vadim/p/7ie0x9pzmm",
            "date_modified": "2024-05-11T10:48:57.221Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/t9gm6knczt",
            "content_html": "To download audio `.mp3` from a page:\n\n```js\n[...document.getElementsByTagName('AUDIO')].map(a => a.src)\n```",
            "url": "https://onp4.com/@vadim/p/t9gm6knczt",
            "date_modified": "2024-04-03T11:41:41.629Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/af3n8t9yk6",
            "content_html": "jQuery is still in development:\n\nhttps://blog.jquery.com/2024/02/06/jquery-4-0-0-beta/",
            "url": "https://onp4.com/@vadim/p/af3n8t9yk6",
            "date_modified": "2024-03-04T14:44:12.339Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/gi6f3adu0v",
            "content_html": "Browser on-disk storage APIs:\n\n- `document.cookie` --- a \"cookie\" is the oldest persistence mechanism, by simply updating the [`document.cookie`](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie) property the browser will synchronously update the value.\n- `localStorage` --- synchronously stores a key-value pair on the disk, historically every write to disk used to be blocking, now browsers seem to optimize this.\n- [WebSQL](https://en.wikipedia.org/wiki/Web_SQL_Database) --- a deprecated SQL standard for the browser.\n- [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) --- the current \"database API\" of the browsers. It used to have asynchronous and synchronous variants, now the synchronous variant is deprecated and works only in worker threads.\n- [`CacheStorage`](https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage) --- key/value storage of service workers.\n- [OPFS](https://developer.mozilla.org/en-US/docs/Web/API/File_System_API/Origin_private_file_system) --- a virtual file system implemented as [FSA](https://developer.mozilla.org/en-US/docs/Web/API/File_System_API). It exposes only asynchronous API from the main threads, but synchronous reads and writes are available from the worker threads. Using the `Atomic.wait` trick, it is possible to achieve synchronous reads and writes from the main thread, too.\n- [FSA (File System Access)](https://wicg.github.io/file-system-access/) --- File System Access, it is implemented using the FSA (File System API), just like, OPFS, but it gives access to real user files on their device. Requires user permission to access a file or a folder, however, the permission object can be stored in IndexDB, which is accessible after browser reload. ",
            "url": "https://onp4.com/@vadim/p/gi6f3adu0v",
            "date_modified": "2024-03-03T19:51:28.806Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/fmuxmxaysp",
            "content_html": "",
            "url": "https://onp4.com/@vadim/p/fmuxmxaysp",
            "date_modified": "2023-08-16T21:59:56.152Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/elnqp3roc7",
            "content_html": "Have Node's implementation of ES modules split the JavaScript ecosystem in two? Similar to how Python ecosystem was split into Python 2 vs Python 3.",
            "url": "https://onp4.com/@vadim/p/elnqp3roc7",
            "date_modified": "2023-07-08T22:22:29.113Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/axuothg11o",
            "content_html": "https://www.aleksandrhovhannisyan.com/blog/interactive-guide-to-javascript-events/",
            "url": "https://onp4.com/@vadim/p/axuothg11o",
            "date_modified": "2023-07-07T07:32:57.587Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/nl9jcosg43",
            "content_html": "\"The default programming language.\"",
            "url": "https://onp4.com/@vadim/p/nl9jcosg43",
            "date_modified": "2023-06-13T11:45:15.099Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/tjto7dj6jc",
            "content_html": "Fast empty object\n\n```js\nconst NullObject = function NullObject() {};\nNullObject.prototype = Object.create(null);\n```\n",
            "url": "https://onp4.com/@vadim/p/tjto7dj6jc",
            "date_modified": "2023-04-24T20:07:29.949Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/dlpkxvvt3h",
            "content_html": "",
            "url": "https://onp4.com/@vadim/p/dlpkxvvt3h",
            "date_modified": "2023-04-19T21:48:11.823Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/6hhelfqdaw",
            "content_html": "Computed property `\"constructor\"` is not picked up as constructor:\n\n```js\nclass A {\n    get ['constructor'] () {\n        return 'foo';\n    }\n}\n```",
            "url": "https://onp4.com/@vadim/p/6hhelfqdaw",
            "date_modified": "2023-04-19T19:20:44.489Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/nvppvgm38b",
            "content_html": "https://blog.logrocket.com/snapshot-flags-node-js-v18-8/",
            "url": "https://onp4.com/@vadim/p/nvppvgm38b",
            "date_modified": "2023-04-14T15:57:29.252Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        },
        {
            "id": "https://onp4.com/@vadim/p/6hr87w1xdr",
            "content_html": "Create an array of given size:\n\n```js\nArray.from({length: 5}, () => 0);\n```",
            "url": "https://onp4.com/@vadim/p/6hr87w1xdr",
            "date_modified": "2023-04-09T21:34:44.161Z",
            "author": {
                "name": "Vadim Dalecky",
                "url": "https://onp4.com/@vadim"
            }
        }
    ]
}