GitHub - tc39/proposal-extensions: Extensions proposal for ECMAScript (original) (raw)

Extensions and :: operator

Proposal status

This is an ECMAScript (JavaScript) proposal in stage 1.

Note: The proposal could be seen as the reshape of the "virtual method" part of old bind operator proposal, see tc39/proposal-bind-operator#56.

Simple examples

Example of ad-hoc extension methods and accessors

// define two extension methods const ::toArray = function () { return [...this] } const ::toSet = function () { return new Set(this) }

// define a extension accessor const ::allDivs = { get() { return this.querySelectorAll('div') } }

// reuse built-in prototype methods and accessors const ::flatMap = Array.prototype.flatMap const ::size = Object.getOwnPropertyDescriptor(Set.prototype, 'size')

// Use extension methods and accesors to calculate // the count of all classes of div element. let classCount = document::allDivs ::flatMap(e => e.classList::toArray()) ::toSet()::size

roughly equals to:

// define two extension methods const $toArray = function () { return [...this] } const $toSet = function () { return new Set(this) }

// define a extension accessor const $allDivs = { get() { return this.querySelectorAll('div') } }

// reuse built-in prototype method and accessor const $flatMap = Array.prototype.flatMap const $size = Object.getOwnPropertyDescriptor(Set.prototype, 'size')

// Use extension methods and accesors to calculate // the count of all classes of div element. let $ $ = $allDivs.get.call(document) $ = flatMap.call(flatMap.call(flatMap.call(, e => $toArray.call(e.classList)) $ = toSet.call(toSet.call(toSet.call() $ = size.get.call(size.get.call(size.get.call() let classCount = $

Example of using constructors or namespace object as extensions

// util.js export const toArray = iterable => [...iterable] export const toSet = iterable => new Set(iterable)

import * as util from './util.js'

const ::allDivs = { get() { return this.querySelectorAll('div') } }

let classCount = document::allDivs ::Array:flatMap( e => e.classList::util:toArray()) ::util:toSet() ::Set:size

roughly equals to:

import * as util from './util.js'

const $allDivs = { get() { return this.querySelectorAll('div') } }

let $ $ = $allDivs.get.call(document) $ = Array.prototype.flatMap.call($, e => util.toArray(e.classList)) $ = util.toSet($) $ = Object.getOwnPropertyDescriptor(Set.prototype, 'size').get.call($) let classCount = $

Changes of the old bind operator proposal

Other matrials