APIs da Web

APIs da Web
===========

Ao escrever código para a Web, há muitas APIs da Web disponíveis. Abaixo está uma lista de todas as APIs e interfaces (tipos de objeto) que você pode usar ao desenvolver seu aplicativo ou site da Web.

As APIs da Web são normalmente usadas com JavaScript, embora isso nem sempre tenha que ser o caso.

Especificações
--------------

Esta é uma lista de todas as APIs disponíveis.

### A

* Audio Output Devices API
Experimental

### B

* Background Fetch API
Experimental
* Background Sync (en-US)
Experimental
* Background Tasks (en-US)
* Badging API (en-US)
* Barcode Detection API (en-US)
Experimental
* Battery API
* Beacon
* Bluetooth API (en-US)
Experimental
* Broadcast Channel API (en-US)

### C

* CSS Counter Styles (en-US)
* CSS Custom Highlight API (en-US)
* CSS Font Loading API (en-US)
* CSS Painting API (en-US)
Experimental
* CSS Properties and Values API (en-US)
* CSS Typed Object Model API (en-US)
* CSSOM
* Canvas API
* Channel Messaging API (en-US)
* Clipboard API (en-US)
* Compression Streams API (en-US)
* Console API
* Contact Picker API (en-US)
Experimental
* Content Index API (en-US)
Experimental
* Cookie Store API (en-US)
Experimental
* Credential Management API (en-US)

### D

* DOM
* Device Memory API (en-US)
* Device Orientation Events (en-US)
* Document Picture-in-Picture API (en-US)
Experimental

### E

* EditContext API (en-US)
Experimental
* Encoding API
* Encrypted Media Extensions (en-US)
* EyeDropper API (en-US)
Experimental

### F

* FedCM API (en-US)
Experimental
* Fetch API
* File API (en-US)
* File System API (en-US)
* File and Directory Entries API (en-US)
* Force Touch Events (en-US)
Non-standard
* Fullscreen API (en-US)

### G

* Gamepad API
* Geolocation API
* Geometry Interfaces (en-US)

### H

* HTML DOM (en-US)
* HTML Drag and Drop API
* HTML Sanitizer API (en-US)
Experimental
* History API
* Houdini API (en-US)

### I

* Idle Detection API (en-US)
Experimental
* Image Capture API (en-US)
Experimental
* IndexedDB
* Ink API (en-US)
Experimental
* Input Device Capabilities API (en-US)
Experimental
* Insertable Streams for MediaStreamTrack API (en-US)
* Intersection Observer API (en-US)

### K

* Keyboard API (en-US)
Experimental

### L

* Launch Handler API (en-US)
Experimental
* Local Font Access API (en-US)
Experimental

### M

* Media Capabilities API (en-US)
* Media Capture and Streams (en-US)
* Media Session API (en-US)
* Media Source Extensions (en-US)
Experimental
* MediaStream Recording (en-US)

### N

* Navigation API (en-US)
Experimental
* Network Information API
Experimental

### P

* Page Visibility API
* Payment Handler API (en-US)
Experimental
* Payment Request API (en-US)
* Performance API (en-US)
* Periodic Background Sync (en-US)
Experimental
* Permissions API (en-US)
* Picture-in-Picture API (en-US)
* Pointer Events (en-US)
* Pointer Lock API (en-US)
* Popover API (en-US)
* Presentation API (en-US)
Experimental
* Prioritized Task Scheduling API (en-US)
* Push API

### R

* Remote Playback API (en-US)
* Reporting API (en-US)
Experimental
* Resize Observer API (en-US)

### S

* SVG (en-US)
* Screen Capture API (en-US)
* Screen Orientation API (en-US)
* Screen Wake Lock API (en-US)
* Selection API (en-US)
* Sensor API (en-US)
* Server Sent Events (en-US)
* Service Workers API
* Shared Storage API (en-US)
Experimental
* Speculation Rules API (en-US)
Experimental
* Storage (en-US)
* Storage Access API (en-US)
* Streams

### T

* Touch Events
* Trusted Types API (en-US)

### U

* UI Events (en-US)
* URL API (en-US)
* URL Pattern API (en-US)
Experimental
* User-Agent Client Hints API (en-US)
Experimental

### V

* Vibration API (en-US)
* View Transitions API (en-US)
Experimental
* VirtualKeyboard API (en-US)
Experimental
* Visual Viewport (en-US)

### W

* Web Animations (en-US)
* Web Audio API
* Web Authentication API (en-US)
* Web Components
* Web Crypto API
* Web Locks API (en-US)
* Web MIDI API (en-US)
* Web NFC API (en-US)
Experimental
* Web Notifications (en-US)
* Web Serial API (en-US)
Experimental
* Web Share API (en-US)
* Web Speech API (en-US)
* Web Storage API
* Web Workers API
* WebCodecs API (en-US)
* WebGL
* WebGPU API (en-US)
Experimental
* WebHID API (en-US)
Experimental
* WebOTP API (en-US)
* WebRTC
* WebTransport API (en-US)
* WebUSB API (en-US)
Experimental
* WebVR API
Non-standard

Deprecated
* WebVTT (en-US)
* WebXR Device API (en-US)
Experimental
* Websockets API
* Window Controls Overlay API (en-US)
Experimental
* Window Management API (en-US)
Experimental

### X

* XMLHttpRequest API (en-US)

Interfaces
----------

Esta é uma lista de todas as interfaces (isto é, tipos de objetos) disponíveis.

### A

* `AbortController` (en-US)
* `AbortSignal`
* `AbsoluteOrientationSensor` (en-US)
* `AbstractRange` (en-US)
* `Accelerometer` (en-US)
Experimental
* `AesCbcParams` (en-US)
* `AesCtrParams` (en-US)
* `AesGcmParams` (en-US)
* `AesKeyGenParams` (en-US)
* `AmbientLightSensor` (en-US)
Experimental
* `AnalyserNode` (en-US)
* `ANGLE_instanced_arrays`
* `Animation`
* `AnimationEffect` (en-US)
* `AnimationEvent`
* `AnimationPlaybackEvent` (en-US)
* `AnimationTimeline` (en-US)
* `Attr`
* `AudioBuffer` (en-US)
* `AudioBufferSourceNode` (en-US)
* `AudioContext`
* `AudioData` (en-US)
Experimental
* `AudioDecoder` (en-US)
Experimental
* `AudioDestinationNode` (en-US)
* `AudioEncoder` (en-US)
Experimental
* `AudioListener` (en-US)
* `AudioNode`
* `AudioParam` (en-US)
* `AudioParamDescriptor` (en-US)
* `AudioParamMap` (en-US)
* `AudioProcessingEvent` (en-US)
Deprecated
* `AudioScheduledSourceNode` (en-US)
* `AudioSinkInfo` (en-US)
Experimental
* `AudioTrack` (en-US)
* `AudioTrackList` (en-US)
* `AudioWorklet` (en-US)
* `AudioWorkletGlobalScope` (en-US)
* `AudioWorkletNode` (en-US)
* `AudioWorkletProcessor` (en-US)
* `AuthenticatorAssertionResponse` (en-US)
* `AuthenticatorAttestationResponse` (en-US)
* `AuthenticatorResponse` (en-US)

### B

* `BackgroundFetchEvent` (en-US)
Experimental
* `BackgroundFetchManager` (en-US)
Experimental
* `BackgroundFetchRecord` (en-US)
Experimental
* `BackgroundFetchRegistration` (en-US)
Experimental
* `BackgroundFetchUpdateUIEvent` (en-US)
Experimental
* `BarcodeDetector` (en-US)
Experimental
* `BarProp` (en-US)
* `BaseAudioContext` (en-US)
* `BatteryManager`
* `BeforeInstallPromptEvent` (en-US)
Experimental

Non-standard
* `BeforeUnloadEvent` (en-US)
* `BiquadFilterNode`
* `Blob`
* `BlobEvent` (en-US)
* `Bluetooth` (en-US)
Experimental
* `BluetoothCharacteristicProperties` (en-US)
Experimental
* `BluetoothDevice` (en-US)
Experimental
* `BluetoothRemoteGATTCharacteristic` (en-US)
Experimental
* `BluetoothRemoteGATTDescriptor` (en-US)
Experimental
* `BluetoothRemoteGATTServer` (en-US)
Experimental
* `BluetoothRemoteGATTService` (en-US)
Experimental
* `BluetoothUUID` (en-US)
* `BroadcastChannel`
* `ByteLengthQueuingStrategy` (en-US)

### C

* `Cache`
* `CacheStorage` (en-US)
* `CanMakePaymentEvent` (en-US)
Experimental
* `CanvasCaptureMediaStreamTrack` (en-US)
* `CanvasGradient` (en-US)
* `CanvasPattern` (en-US)
* `CanvasRenderingContext2D`
* `CaptureController` (en-US)
Experimental
* `CaretPosition` (en-US)
Experimental
* `CDATASection` (en-US)
* `ChannelMergerNode` (en-US)
* `ChannelSplitterNode` (en-US)
* `CharacterBoundsUpdateEvent` (en-US)
Experimental
* `CharacterData`
* `Client` (en-US)
* `Clients` (en-US)
* `Clipboard` (en-US)
* `ClipboardEvent`
* `ClipboardItem` (en-US)
* `CloseEvent`
* `Comment` (en-US)
* `CompositionEvent` (en-US)
* `CompressionStream` (en-US)
* `console`
* `ConstantSourceNode` (en-US)
* `ContactAddress` (en-US)
Experimental
* `ContactsManager` (en-US)
Experimental
* `ContentIndex` (en-US)
Experimental
* `ContentIndexEvent` (en-US)
Experimental
* `ContentVisibilityAutoStateChangeEvent` (en-US)
Experimental
* `ConvolverNode` (en-US)
* `CookieChangeEvent` (en-US)
Experimental
* `CookieStore` (en-US)
Experimental
* `CookieStoreManager` (en-US)
Experimental
* `CountQueuingStrategy` (en-US)
* `Credential` (en-US)
* `CredentialsContainer` (en-US)
* `Crypto`
* `CryptoKey`
* `CryptoKeyPair` (en-US)
* `CSPViolationReportBody` (en-US)
* `CSS`
* `CSSAnimation` (en-US)
* `CSSConditionRule` (en-US)
* `CSSContainerRule` (en-US)
* `CSSCounterStyleRule` (en-US)
* `CSSFontFaceRule` (en-US)
* `CSSFontFeatureValuesRule` (en-US)
* `CSSFontPaletteValuesRule` (en-US)
* `CSSGroupingRule` (en-US)
* `CSSImageValue` (en-US)
* `CSSImportRule` (en-US)
* `CSSKeyframeRule` (en-US)
* `CSSKeyframesRule` (en-US)
* `CSSKeywordValue` (en-US)
* `CSSLayerBlockRule` (en-US)
* `CSSLayerStatementRule` (en-US)
* `CSSMathInvert` (en-US)
* `CSSMathMax` (en-US)
* `CSSMathMin` (en-US)
* `CSSMathNegate` (en-US)
* `CSSMathProduct` (en-US)
* `CSSMathSum` (en-US)
* `CSSMathValue` (en-US)
* `CSSMatrixComponent` (en-US)
* `CSSMediaRule` (en-US)
* `CSSNamespaceRule` (en-US)
* `CSSNumericArray` (en-US)
* `CSSNumericValue` (en-US)
* `CSSPageRule` (en-US)
* `CSSPerspective` (en-US)
* `CSSPositionValue` (en-US)
Non-standard

Deprecated
* `CSSPrimitiveValue` (en-US)
Deprecated
* `CSSPropertyRule` (en-US)
* `CSSPseudoElement` (en-US)
Experimental
* `CSSRotate` (en-US)
* `CSSRule` (en-US)
* `CSSRuleList` (en-US)
* `CSSScale` (en-US)
* `CSSScopeRule` (en-US)
Experimental
* `CSSSkew` (en-US)
* `CSSSkewX` (en-US)
* `CSSSkewY` (en-US)
* `CSSStartingStyleRule` (en-US)
Experimental
* `CSSStyleDeclaration` (en-US)
* `CSSStyleRule` (en-US)
* `CSSStyleSheet` (en-US)
* `CSSStyleValue` (en-US)
* `CSSSupportsRule` (en-US)
* `CSSTransformComponent` (en-US)
* `CSSTransformValue` (en-US)
* `CSSTransition` (en-US)
* `CSSTranslate` (en-US)
* `CSSUnitValue` (en-US)
* `CSSUnparsedValue` (en-US)
* `CSSValue` (en-US)
Deprecated
* `CSSValueList` (en-US)
Deprecated
* `CSSVariableReferenceValue` (en-US)
* `CustomElementRegistry`
* `CustomEvent` (en-US)
* `CustomStateSet` (en-US)
Experimental

### D

* `DataTransfer`
* `DataTransferItem` (en-US)
* `DataTransferItemList` (en-US)
* `DecompressionStream` (en-US)
* `DedicatedWorkerGlobalScope` (en-US)
* `DelayNode` (en-US)
* `DeprecationReportBody` (en-US)
Experimental
* `DeviceMotionEvent` (en-US)
* `DeviceMotionEventAcceleration`
* `DeviceMotionEventRotationRate`
* `DeviceOrientationEvent` (en-US)
* `DirectoryEntrySync` (en-US)
Non-standard

Deprecated
* `DirectoryReaderSync` (en-US)
Non-standard

Deprecated
* `Document`
* `DocumentFragment`
* `DocumentPictureInPicture` (en-US)
Experimental
* `DocumentPictureInPictureEvent` (en-US)
Experimental
* `DocumentTimeline` (en-US)
* `DocumentType` (en-US)
* `DOMError` (en-US)
Deprecated
* `DOMException` (en-US)
* `DOMHighResTimeStamp` (en-US)
* `DOMImplementation` (en-US)
* `DOMMatrix` (WebKitCSSMatrix) (en-US)
* `DOMMatrixReadOnly` (en-US)
* `DOMParser` (en-US)
* `DOMPoint` (en-US)
* `DOMPointReadOnly` (en-US)
* `DOMQuad` (en-US)
* `DOMRect` (en-US)
* `DOMRectReadOnly` (en-US)
* `DOMStringList`
* `DOMStringMap`
* `DOMTokenList` (en-US)
* `DragEvent` (en-US)
* `DynamicsCompressorNode` (en-US)

### E

* `EcdhKeyDeriveParams` (en-US)
* `EcdsaParams` (en-US)
* `EcKeyGenParams` (en-US)
* `EcKeyImportParams` (en-US)
* `EditContext` (en-US)
Experimental
* `Element`
* `ElementInternals` (en-US)
* `EncodedAudioChunk` (en-US)
Experimental
* `EncodedVideoChunk` (en-US)
* `ErrorEvent` (en-US)
* `Event`
* `EventCounts` (en-US)
* `EventSource`
* `EventTarget`
* `ExtendableCookieChangeEvent` (en-US)
* `ExtendableEvent` (en-US)
* `ExtendableMessageEvent` (en-US)
* `EyeDropper` (en-US)
Experimental

### F

* `FeaturePolicy` (en-US)
Experimental
* `FederatedCredential` (en-US)
Experimental
* `FetchEvent` (en-US)
* `File`
* `FileEntrySync` (en-US)
Non-standard

Deprecated
* `FileList`
* `FileReader`
* `FileReaderSync` (en-US)
* `FileSystem` (en-US)
* `FileSystemDirectoryEntry` (en-US)
* `FileSystemDirectoryHandle` (en-US)
* `FileSystemDirectoryReader` (en-US)
* `FileSystemEntry` (en-US)
* `FileSystemFileEntry` (en-US)
* `FileSystemFileHandle` (en-US)
* `FileSystemHandle` (en-US)
* `FileSystemSync` (en-US)
Non-standard

Deprecated
* `FileSystemSyncAccessHandle` (en-US)
* `FileSystemWritableFileStream` (en-US)
* `FocusEvent` (en-US)
* `FontData` (en-US)
Experimental
* `FontFace` (en-US)
* `FontFaceSet` (en-US)
* `FontFaceSetLoadEvent` (en-US)
* `FormData`
* `FormDataEvent` (en-US)
* `FragmentDirective` (en-US)
Experimental

### G

* `GainNode` (en-US)
* `Gamepad` (en-US)
* `GamepadButton` (en-US)
* `GamepadEvent` (en-US)
* `GamepadHapticActuator` (en-US)
* `GamepadPose` (en-US)
Experimental
* `Geolocation`
* `GeolocationCoordinates`
* `GeolocationPosition`
* `GeolocationPositionError`
* `GestureEvent` (en-US)
Non-standard
* `GPU` (en-US)
Experimental
* `GPUAdapter` (en-US)
Experimental
* `GPUAdapterInfo` (en-US)
Experimental
* `GPUBindGroup` (en-US)
Experimental
* `GPUBindGroupLayout` (en-US)
Experimental
* `GPUBuffer` (en-US)
Experimental
* `GPUCanvasContext` (en-US)
Experimental
* `GPUCommandBuffer` (en-US)
Experimental
* `GPUCommandEncoder` (en-US)
Experimental
* `GPUCompilationInfo` (en-US)
Experimental
* `GPUCompilationMessage` (en-US)
Experimental
* `GPUComputePassEncoder` (en-US)
Experimental
* `GPUComputePipeline` (en-US)
Experimental
* `GPUDevice` (en-US)
Experimental
* `GPUDeviceLostInfo` (en-US)
Experimental
* `GPUError` (en-US)
Experimental
* `GPUExternalTexture` (en-US)
Experimental
* `GPUInternalError` (en-US)
Experimental
* `GPUOutOfMemoryError` (en-US)
Experimental
* `GPUPipelineError` (en-US)
Experimental
* `GPUPipelineLayout` (en-US)
Experimental
* `GPUQuerySet` (en-US)
Experimental
* `GPUQueue` (en-US)
Experimental
* `GPURenderBundle` (en-US)
Experimental
* `GPURenderBundleEncoder` (en-US)
Experimental
* `GPURenderPassEncoder` (en-US)
Experimental
* `GPURenderPipeline` (en-US)
Experimental
* `GPUSampler` (en-US)
Experimental
* `GPUShaderModule` (en-US)
Experimental
* `GPUSupportedFeatures` (en-US)
Experimental
* `GPUSupportedLimits` (en-US)
Experimental
* `GPUTexture` (en-US)
Experimental
* `GPUTextureView` (en-US)
Experimental
* `GPUUncapturedErrorEvent` (en-US)
Experimental
* `GPUValidationError` (en-US)
Experimental
* `GravitySensor` (en-US)
* `Gyroscope` (en-US)

### H

* `HashChangeEvent` (en-US)
* `Headers` (en-US)
* `HID` (en-US)
Experimental
* `HIDConnectionEvent` (en-US)
Experimental
* `HIDDevice` (en-US)
Experimental
* `HIDInputReportEvent` (en-US)
Experimental
* `Highlight` (en-US)
* `HighlightRegistry` (en-US)
* `History` (en-US)
* `HkdfParams` (en-US)
* `HmacImportParams` (en-US)
* `HmacKeyGenParams` (en-US)
* `HMDVRDevice` (en-US)
Non-standard

Deprecated
* `HTMLAllCollection` (en-US)
* `HTMLAnchorElement` (en-US)
* `HTMLAreaElement` (en-US)
* `HTMLAudioElement` (en-US)
* `HTMLBaseElement` (en-US)
* `HTMLBodyElement` (en-US)
* `HTMLBRElement` (en-US)
* `HTMLButtonElement` (en-US)
* `HTMLCanvasElement` (en-US)
* `HTMLCollection`
* `HTMLDataElement` (en-US)
* `HTMLDataListElement` (en-US)
* `HTMLDetailsElement` (en-US)
* `HTMLDialogElement` (en-US)
* `HTMLDivElement`
* `HTMLDListElement` (en-US)
* `HTMLDocument` (en-US)
* `HTMLElement` (en-US)
* `HTMLEmbedElement` (en-US)
* `HTMLFieldSetElement` (en-US)
* `HTMLFontElement` (en-US)
Deprecated
* `HTMLFormControlsCollection` (en-US)
* `HTMLFormElement` (en-US)
* `HTMLFrameSetElement` (en-US)
Deprecated
* `HTMLHeadElement` (en-US)
* `HTMLHeadingElement` (en-US)
* `HTMLHRElement` (en-US)
* `HTMLHtmlElement` (en-US)
* `HTMLIFrameElement` (en-US)
* `HTMLImageElement` (en-US)
* `HTMLInputElement`
* `HTMLLabelElement` (en-US)
* `HTMLLegendElement` (en-US)
* `HTMLLIElement` (en-US)
* `HTMLLinkElement` (en-US)
* `HTMLMapElement` (en-US)
* `HTMLMarqueeElement` (en-US)
Deprecated
* `HTMLMediaElement` (en-US)
* `HTMLMenuElement` (en-US)
* `HTMLMenuItemElement` (en-US)
Non-standard

Deprecated
* `HTMLMetaElement` (en-US)
* `HTMLMeterElement` (en-US)
* `HTMLModElement` (en-US)
* `HTMLObjectElement` (en-US)
* `HTMLOListElement` (en-US)
* `HTMLOptGroupElement` (en-US)
* `HTMLOptionElement` (en-US)
* `HTMLOptionsCollection` (en-US)
* `HTMLOutputElement` (en-US)
* `HTMLParagraphElement` (en-US)
* `HTMLParamElement` (en-US)
Deprecated
* `HTMLPictureElement` (en-US)
* `HTMLPreElement` (en-US)
* `HTMLProgressElement` (en-US)
* `HTMLQuoteElement` (en-US)
* `HTMLScriptElement` (en-US)
* `HTMLSelectElement` (en-US)
* `HTMLSlotElement`
* `HTMLSourceElement` (en-US)
* `HTMLSpanElement`
* `HTMLStyleElement` (en-US)
* `HTMLTableCaptionElement` (en-US)
* `HTMLTableCellElement` (en-US)
* `HTMLTableColElement` (en-US)
* `HTMLTableElement` (en-US)
* `HTMLTableRowElement` (en-US)
* `HTMLTableSectionElement` (en-US)
* `HTMLTemplateElement` (en-US)
* `HTMLTextAreaElement` (en-US)
* `HTMLTimeElement` (en-US)
* `HTMLTitleElement` (en-US)
* `HTMLTrackElement` (en-US)
* `HTMLUListElement` (en-US)
* `HTMLUnknownElement` (en-US)
* `HTMLVideoElement` (en-US)

### I

* `IDBCursor`
* `IDBCursorWithValue` (en-US)
* `IDBDatabase` (en-US)
* `IDBFactory`
* `IDBIndex` (en-US)
* `IDBKeyRange` (en-US)
* `IDBLocaleAwareKeyRange` (en-US)
Experimental

Non-standard
* `IDBObjectStore` (en-US)
* `IDBOpenDBRequest` (en-US)
* `IDBRequest` (en-US)
* `IDBTransaction` (en-US)
* `IDBVersionChangeEvent` (en-US)
* `IdentityCredential` (en-US)
Experimental
* `IdentityProvider` (en-US)
Experimental
* `IdleDeadline` (en-US)
* `IdleDetector` (en-US)
Experimental
* `IIRFilterNode` (en-US)
* `ImageBitmap` (en-US)
* `ImageBitmapRenderingContext` (en-US)
* `ImageCapture`
Experimental
* `ImageData` (en-US)
* `ImageDecoder` (en-US)
Experimental
* `ImageTrack` (en-US)
Experimental
* `ImageTrackList` (en-US)
Experimental
* `Ink` (en-US)
Experimental
* `InkPresenter` (en-US)
Experimental
* `InputDeviceCapabilities` (en-US)
Experimental
* `InputDeviceInfo` (en-US)
* `InputEvent` (en-US)
* `InstallEvent` (en-US)
Non-standard

Deprecated
* `IntersectionObserver` (en-US)
* `IntersectionObserverEntry` (en-US)
* `InterventionReportBody` (en-US)
Experimental

### K

* `Keyboard` (en-US)
Experimental
* `KeyboardEvent` (en-US)
* `KeyboardLayoutMap` (en-US)
Experimental
* `KeyframeEffect` (en-US)

### L

* `LargestContentfulPaint` (en-US)
* `LaunchParams` (en-US)
Experimental
* `LaunchQueue` (en-US)
Experimental
* `LayoutShift` (en-US)
Experimental
* `LayoutShiftAttribution` (en-US)
Experimental
* `LinearAccelerationSensor` (en-US)
* `Location`
* `Lock` (en-US)
* `LockManager` (en-US)

### M

* `Magnetometer` (en-US)
Experimental
* `MathMLElement` (en-US)
* `MediaCapabilities` (en-US)
* `MediaDeviceInfo` (en-US)
* `MediaDevices`
* `MediaElementAudioSourceNode` (en-US)
* `MediaEncryptedEvent` (en-US)
* `MediaError` (en-US)
* `MediaKeyMessageEvent` (en-US)
* `MediaKeys` (en-US)
* `MediaKeySession` (en-US)
* `MediaKeyStatusMap` (en-US)
* `MediaKeySystemAccess` (en-US)
* `MediaList` (en-US)
* `MediaMetadata` (en-US)
* `MediaQueryList` (en-US)
* `MediaQueryListEvent` (en-US)
* `MediaRecorder` (en-US)
* `MediaRecorderErrorEvent` (en-US)
Non-standard

Deprecated
* `MediaSession` (en-US)
* `MediaSource` (en-US)
* `MediaSourceHandle` (en-US)
Experimental
* `MediaStream` (en-US)
* `MediaStreamAudioDestinationNode` (en-US)
* `MediaStreamAudioSourceNode` (en-US)
* `MediaStreamEvent` (en-US)
Non-standard

Deprecated
* `MediaStreamTrack` (en-US)
* `MediaStreamTrackAudioSourceNode` (en-US)
* `MediaStreamTrackEvent` (en-US)
* `MediaStreamTrackGenerator` (en-US)
Experimental

Non-standard
* `MediaStreamTrackProcessor` (en-US)
Experimental
* `MediaTrackConstraints` (en-US)
* `MediaTrackSettings` (en-US)
* `MediaTrackSupportedConstraints` (en-US)
* `MerchantValidationEvent` (en-US)
Deprecated
* `MessageChannel`
* `MessageEvent` (en-US)
* `MessagePort` (en-US)
* `Metadata` (en-US)
Experimental

Non-standard
* `MIDIAccess` (en-US)
* `MIDIConnectionEvent` (en-US)
* `MIDIInput` (en-US)
* `MIDIInputMap` (en-US)
* `MIDIMessageEvent` (en-US)
* `MIDIOutput` (en-US)
* `MIDIOutputMap` (en-US)
* `MIDIPort` (en-US)
* `MimeType` (en-US)
Deprecated
* `MimeTypeArray` (en-US)
Deprecated
* `MouseEvent`
* `MouseScrollEvent` (en-US)
Non-standard

Deprecated
* `MutationEvent` (en-US)
Deprecated
* `MutationObserver`
* `MutationRecord` (en-US)

### N

* `NamedNodeMap` (en-US)
* `NavigateEvent` (en-US)
Experimental
* `Navigation` (en-US)
Experimental
* `NavigationCurrentEntryChangeEvent` (en-US)
Experimental
* `NavigationDestination` (en-US)
Experimental
* `NavigationHistoryEntry` (en-US)
Experimental
* `NavigationPreloadManager` (en-US)
* `NavigationTransition` (en-US)
Experimental
* `Navigator` (en-US)
* `NavigatorUAData` (en-US)
Experimental
* `NDEFMessage` (en-US)
Experimental
* `NDEFReader` (en-US)
Experimental
* `NDEFReadingEvent` (en-US)
Experimental
* `NDEFRecord` (en-US)
Experimental
* `NetworkInformation` (en-US)
Experimental
* `Node`
* `NodeIterator` (en-US)
* `NodeList`
* `Notification`
* `NotificationEvent` (en-US)

### O

* `OES_draw_buffers_indexed` (en-US)
* `OfflineAudioCompletionEvent` (en-US)
* `OfflineAudioContext`
* `OffscreenCanvas` (en-US)
* `OffscreenCanvasRenderingContext2D` (en-US)
* `OrientationSensor` (en-US)
* `OscillatorNode` (en-US)
* `OTPCredential` (en-US)
Experimental
* `OverconstrainedError` (en-US)

### P

* `PageTransitionEvent` (en-US)
* `PaintWorkletGlobalScope` (en-US)
Experimental
* `PannerNode` (en-US)
* `PasswordCredential` (en-US)
Experimental
* `Path2D`
* `PaymentAddress` (en-US)
Non-standard

Deprecated
* `PaymentManager` (en-US)
Experimental
* `PaymentMethodChangeEvent` (en-US)
* `PaymentRequest` (en-US)
* `PaymentRequestEvent` (en-US)
Experimental
* `PaymentRequestUpdateEvent` (en-US)
* `PaymentResponse` (en-US)
* `Pbkdf2Params` (en-US)
* `Performance` (en-US)
* `PerformanceElementTiming` (en-US)
Experimental
* `PerformanceEntry` (en-US)
* `PerformanceEventTiming` (en-US)
* `PerformanceLongTaskTiming` (en-US)
Experimental
* `PerformanceMark` (en-US)
* `PerformanceMeasure` (en-US)
* `PerformanceNavigation` (en-US)
Deprecated
* `PerformanceNavigationTiming` (en-US)
* `PerformanceObserver` (en-US)
* `PerformanceObserverEntryList` (en-US)
* `PerformancePaintTiming` (en-US)
* `PerformanceResourceTiming` (en-US)
* `PerformanceServerTiming` (en-US)
* `PerformanceTiming` (en-US)
Deprecated
* `PeriodicSyncEvent` (en-US)
Experimental
* `PeriodicSyncManager` (en-US)
Experimental
* `PeriodicWave` (en-US)
* `Permissions` (en-US)
* `PermissionStatus` (en-US)
* `PictureInPictureEvent` (en-US)
* `PictureInPictureWindow` (en-US)
* `Plugin` (en-US)
Deprecated
* `PluginArray` (en-US)
Deprecated
* `Point` (en-US)
Non-standard

Deprecated
* `PointerEvent` (en-US)
* `PopStateEvent` (en-US)
* `PositionSensorVRDevice` (en-US)
Non-standard

Deprecated
* `Presentation` (en-US)
Experimental
* `PresentationAvailability` (en-US)
Experimental
* `PresentationConnection` (en-US)
Experimental
* `PresentationConnectionAvailableEvent` (en-US)
Experimental
* `PresentationConnectionCloseEvent` (en-US)
Experimental
* `PresentationConnectionList` (en-US)
Experimental
* `PresentationReceiver` (en-US)
Experimental
* `PresentationRequest` (en-US)
Experimental
* `ProcessingInstruction`
* `ProgressEvent` (en-US)
* `PromiseRejectionEvent` (en-US)
* `PublicKeyCredential` (en-US)
* `PushEvent` (en-US)
* `PushManager`
* `PushMessageData` (en-US)
* `PushSubscription` (en-US)
* `PushSubscriptionOptions` (en-US)

### R

* `RadioNodeList` (en-US)
* `Range` (en-US)
* `ReadableByteStreamController` (en-US)
* `ReadableStream` (en-US)
* `ReadableStreamBYOBReader` (en-US)
* `ReadableStreamBYOBRequest` (en-US)
* `ReadableStreamDefaultController` (en-US)
* `ReadableStreamDefaultReader` (en-US)
* `RelativeOrientationSensor` (en-US)
* `RemotePlayback` (en-US)
* `Report` (en-US)
* `ReportBody` (en-US)
* `ReportingObserver` (en-US)
* `Request`
* `ResizeObserver` (en-US)
* `ResizeObserverEntry` (en-US)
* `ResizeObserverSize` (en-US)
* `Response`
* `RsaHashedImportParams` (en-US)
* `RsaHashedKeyGenParams` (en-US)
* `RsaOaepParams` (en-US)
* `RsaPssParams` (en-US)
* `RTCAudioSourceStats` (en-US)
* `RTCCertificate`
* `RTCCertificateStats` (en-US)
* `RTCDataChannel`
* `RTCDataChannelEvent` (en-US)
* `RTCDtlsTransport` (en-US)
* `RTCDTMFSender` (en-US)
* `RTCDTMFToneChangeEvent` (en-US)
* `RTCEncodedAudioFrame` (en-US)
* `RTCEncodedVideoFrame` (en-US)
* `RTCError` (en-US)
* `RTCErrorEvent` (en-US)
* `RTCIceCandidate` (en-US)
* `RTCIceCandidatePair` (en-US)
* `RTCIceCandidatePairStats` (en-US)
* `RTCIceCandidateStats` (en-US)
* `RTCIceParameters` (en-US)
* `RTCIceTransport`
* `RTCIdentityAssertion` (en-US)
Experimental
* `RTCInboundRtpStreamStats` (en-US)
* `RTCOutboundRtpStreamStats` (en-US)
* `RTCPeerConnection` (en-US)
* `RTCPeerConnectionIceErrorEvent` (en-US)
* `RTCPeerConnectionIceEvent` (en-US)
* `RTCPeerConnectionStats` (en-US)
* `RTCRemoteOutboundRtpStreamStats` (en-US)
* `RTCRtpCodecParameters` (en-US)
* `RTCRtpReceiver` (en-US)
* `RTCRtpScriptTransform` (en-US)
* `RTCRtpScriptTransformer` (en-US)
* `RTCRtpSender` (en-US)
* `RTCRtpStreamStats` (en-US)
* `RTCRtpTransceiver` (en-US)
* `RTCSctpTransport` (en-US)
* `RTCSessionDescription` (en-US)
* `RTCStatsReport` (en-US)
* `RTCTrackEvent` (en-US)
* `RTCTransformEvent` (en-US)
* `RTCTransportStats` (en-US)

### S

* `Sanitizer` (en-US)
Experimental
* `Scheduler` (en-US)
* `Scheduling` (en-US)
Experimental
* `Screen` (en-US)
* `ScreenDetailed` (en-US)
Experimental
* `ScreenDetails` (en-US)
Experimental
* `ScreenOrientation` (en-US)
* `ScriptProcessorNode` (en-US)
Deprecated
* `ScrollTimeline` (en-US)
Experimental
* `SecurePaymentConfirmationRequest` (en-US)
* `SecurityPolicyViolationEvent` (en-US)
* `Selection`
* `Sensor` (en-US)
* `SensorErrorEvent` (en-US)
* `Serial` (en-US)
Experimental
* `SerialPort` (en-US)
Experimental
* `ServiceWorker` (en-US)
* `ServiceWorkerContainer` (en-US)
* `ServiceWorkerGlobalScope` (en-US)
* `ServiceWorkerRegistration` (en-US)
* `ShadowRoot` (en-US)
* `SharedStorage` (en-US)
Experimental
* `SharedStorageOperation` (en-US)
Experimental
* `SharedStorageRunOperation` (en-US)
Experimental
* `SharedStorageSelectURLOperation` (en-US)
Experimental
* `SharedStorageWorklet` (en-US)
Experimental
* `SharedStorageWorkletGlobalScope` (en-US)
Experimental
* `SharedWorker` (en-US)
* `SharedWorkerGlobalScope` (en-US)
* `SourceBuffer` (en-US)
* `SourceBufferList` (en-US)
* `SpeechGrammar`
Experimental
* `SpeechGrammarList` (en-US)
Experimental
* `SpeechRecognition` (en-US)
* `SpeechRecognitionAlternative` (en-US)
* `SpeechRecognitionErrorEvent` (en-US)
* `SpeechRecognitionEvent` (en-US)
* `SpeechRecognitionResult` (en-US)
* `SpeechRecognitionResultList` (en-US)
* `SpeechSynthesis`
* `SpeechSynthesisErrorEvent` (en-US)
* `SpeechSynthesisEvent` (en-US)
* `SpeechSynthesisUtterance` (en-US)
* `SpeechSynthesisVoice` (en-US)
* `StaticRange` (en-US)
* `StereoPannerNode` (en-US)
* `Storage`
* `StorageEvent` (en-US)
* `StorageManager`
* `StylePropertyMap` (en-US)
* `StylePropertyMapReadOnly` (en-US)
* `StyleSheet` (en-US)
* `StyleSheetList` (en-US)
* `SubmitEvent` (en-US)
* `SubtleCrypto`
* `SVGAElement`
* `SVGAngle` (en-US)
* `SVGAnimateColorElement` (en-US)
Deprecated
* `SVGAnimatedAngle` (en-US)
* `SVGAnimatedBoolean` (en-US)
* `SVGAnimatedEnumeration` (en-US)
* `SVGAnimatedInteger` (en-US)
* `SVGAnimatedLength` (en-US)
* `SVGAnimatedLengthList` (en-US)
* `SVGAnimatedNumber` (en-US)
* `SVGAnimatedNumberList` (en-US)
* `SVGAnimatedPreserveAspectRatio` (en-US)
* `SVGAnimatedRect` (en-US)
* `SVGAnimatedString` (en-US)
* `SVGAnimatedTransformList` (en-US)
* `SVGAnimateElement` (en-US)
* `SVGAnimateMotionElement` (en-US)
* `SVGAnimateTransformElement`
* `SVGAnimationElement` (en-US)
* `SVGCircleElement` (en-US)
* `SVGClipPathElement` (en-US)
* `SVGComponentTransferFunctionElement` (en-US)
* `SVGCursorElement` (en-US)
Deprecated
* `SVGDefsElement` (en-US)
* `SVGDescElement` (en-US)
* `SVGElement` (en-US)
* `SVGEllipseElement` (en-US)
* `SVGEvent` (en-US)
* `SVGFEBlendElement` (en-US)
* `SVGFEColorMatrixElement` (en-US)
* `SVGFEComponentTransferElement` (en-US)
* `SVGFECompositeElement` (en-US)
* `SVGFEConvolveMatrixElement` (en-US)
* `SVGFEDiffuseLightingElement` (en-US)
* `SVGFEDisplacementMapElement` (en-US)
* `SVGFEDistantLightElement` (en-US)
* `SVGFEDropShadowElement` (en-US)
* `SVGFEFloodElement` (en-US)
* `SVGFEFuncAElement` (en-US)
* `SVGFEFuncBElement` (en-US)
* `SVGFEFuncGElement` (en-US)
* `SVGFEFuncRElement` (en-US)
* `SVGFEGaussianBlurElement` (en-US)
* `SVGFEImageElement` (en-US)
* `SVGFEMergeElement` (en-US)
* `SVGFEMergeNodeElement` (en-US)
* `SVGFEMorphologyElement` (en-US)
* `SVGFEOffsetElement` (en-US)
* `SVGFEPointLightElement` (en-US)
* `SVGFESpecularLightingElement` (en-US)
* `SVGFESpotLightElement` (en-US)
* `SVGFETileElement` (en-US)
* `SVGFETurbulenceElement` (en-US)
* `SVGFilterElement` (en-US)
* `SVGFontElement` (en-US)
Deprecated
* `SVGFontFaceElement` (en-US)
Deprecated
* `SVGFontFaceFormatElement` (en-US)
Deprecated
* `SVGFontFaceNameElement` (en-US)
Deprecated
* `SVGFontFaceSrcElement` (en-US)
Deprecated
* `SVGFontFaceUriElement` (en-US)
Deprecated
* `SVGForeignObjectElement` (en-US)
* `SVGGElement` (en-US)
* `SVGGeometryElement` (en-US)
* `SVGGlyphElement` (en-US)
Deprecated
* `SVGGlyphRefElement` (en-US)
Deprecated
* `SVGGradientElement` (en-US)
* `SVGGraphicsElement` (en-US)
* `SVGHKernElement` (en-US)
Deprecated
* `SVGImageElement` (en-US)
* `SVGLength` (en-US)
* `SVGLengthList` (en-US)
* `SVGLinearGradientElement` (en-US)
* `SVGLineElement` (en-US)
* `SVGMarkerElement` (en-US)
* `SVGMaskElement` (en-US)
* `SVGMetadataElement` (en-US)
* `SVGMissingGlyphElement` (en-US)
Deprecated
* `SVGMPathElement` (en-US)
* `SVGNumber` (en-US)
* `SVGNumberList` (en-US)
* `SVGPathElement` (en-US)
* `SVGPatternElement` (en-US)
* `SVGPoint` (en-US)
Deprecated
* `SVGPointList` (en-US)
* `SVGPolygonElement` (en-US)
* `SVGPolylineElement` (en-US)
* `SVGPreserveAspectRatio` (en-US)
* `SVGRadialGradientElement` (en-US)
* `SVGRect` (en-US)
* `SVGRectElement` (en-US)
* `SVGRenderingIntent` (en-US)
Deprecated
* `SVGScriptElement` (en-US)
* `SVGSetElement` (en-US)
* `SVGStopElement` (en-US)
* `SVGStringList` (en-US)
* `SVGStyleElement` (en-US)
* `SVGSVGElement` (en-US)
* `SVGSwitchElement` (en-US)
* `SVGSymbolElement` (en-US)
* `SVGTextContentElement` (en-US)
* `SVGTextElement` (en-US)
* `SVGTextPathElement` (en-US)
* `SVGTextPositioningElement` (en-US)
* `SVGTitleElement` (en-US)
* `SVGTransform` (en-US)
* `SVGTransformList` (en-US)
* `SVGTRefElement` (en-US)
Deprecated
* `SVGTSpanElement` (en-US)
* `SVGUnitTypes` (en-US)
* `SVGUseElement` (en-US)
* `SVGViewElement` (en-US)
* `SVGVKernElement` (en-US)
Deprecated
* `SyncEvent` (en-US)
Experimental
* `SyncManager` (en-US)
Experimental

### T

* `TaskAttributionTiming` (en-US)
Experimental
* `TaskController` (en-US)
* `TaskPriorityChangeEvent` (en-US)
* `TaskSignal` (en-US)
* `Text` (en-US)
* `TextDecoder` (en-US)
* `TextDecoderStream` (en-US)
* `TextEncoder` (en-US)
* `TextEncoderStream` (en-US)
* `TextFormat` (en-US)
Experimental
* `TextFormatUpdateEvent` (en-US)
Experimental
* `TextMetrics` (en-US)
* `TextTrack` (en-US)
* `TextTrackCue` (en-US)
* `TextTrackCueList` (en-US)
* `TextTrackList` (en-US)
* `TextUpdateEvent` (en-US)
Experimental
* `TimeEvent` (en-US)
* `TimeRanges` (en-US)
* `ToggleEvent` (en-US)
* `Touch` (en-US)
* `TouchEvent` (en-US)
* `TouchList` (en-US)
* `TrackEvent` (en-US)
* `TransformStream` (en-US)
* `TransformStreamDefaultController` (en-US)
* `TransitionEvent` (en-US)
* `TreeWalker` (en-US)
* `TrustedHTML` (en-US)
* `TrustedScript` (en-US)
* `TrustedScriptURL` (en-US)
* `TrustedTypePolicy` (en-US)
* `TrustedTypePolicyFactory` (en-US)

### U

* `UIEvent` (en-US)
* `URL`
* `URLPattern` (en-US)
Experimental
* `URLSearchParams`
* `USB` (en-US)
Experimental
* `USBAlternateInterface` (en-US)
Experimental
* `USBConfiguration` (en-US)
Experimental
* `USBConnectionEvent` (en-US)
Experimental
* `USBDevice` (en-US)
Experimental
* `USBEndpoint` (en-US)
Experimental
* `USBInterface` (en-US)
Experimental
* `USBInTransferResult` (en-US)
Experimental
* `USBIsochronousInTransferPacket` (en-US)
Experimental
* `USBIsochronousInTransferResult` (en-US)
Experimental
* `USBIsochronousOutTransferPacket` (en-US)
Experimental
* `USBIsochronousOutTransferResult` (en-US)
Experimental
* `USBOutTransferResult` (en-US)
Experimental
* `UserActivation` (en-US)

### V

* `ValidityState`
* `VideoColorSpace` (en-US)
* `VideoDecoder` (en-US)
* `VideoEncoder` (en-US)
* `VideoFrame` (en-US)
* `VideoPlaybackQuality` (en-US)
* `VideoTrack` (en-US)
* `VideoTrackList` (en-US)
* `ViewTimeline` (en-US)
Experimental
* `ViewTransition` (en-US)
Experimental
* `VirtualKeyboard` (en-US)
Experimental
* `VisibilityStateEntry` (en-US)
Experimental
* `VisualViewport` (en-US)
* `VRDisplay` (en-US)
Non-standard

Deprecated
* `VRDisplayCapabilities` (en-US)
Non-standard

Deprecated
* `VRDisplayEvent` (en-US)
Non-standard

Deprecated
* `VREyeParameters` (en-US)
Non-standard

Deprecated
* `VRFieldOfView` (en-US)
Non-standard

Deprecated
* `VRFrameData` (en-US)
Non-standard

Deprecated
* `VRLayerInit` (en-US)
Deprecated
* `VRPose` (en-US)
Non-standard

Deprecated
* `VRStageParameters` (en-US)
Non-standard

Deprecated
* `VTTCue` (en-US)
* `VTTRegion` (en-US)

### W

* `WakeLock` (en-US)
* `WakeLockSentinel` (en-US)
* `WaveShaperNode` (en-US)
* `WebGL2RenderingContext` (en-US)
* `WebGLActiveInfo` (en-US)
* `WebGLBuffer` (en-US)
* `WebGLContextEvent` (en-US)
* `WebGLFramebuffer` (en-US)
* `WebGLObject` (en-US)
* `WebGLProgram` (en-US)
* `WebGLQuery` (en-US)
* `WebGLRenderbuffer` (en-US)
* `WebGLRenderingContext` (en-US)
* `WebGLSampler` (en-US)
* `WebGLShader` (en-US)
* `WebGLShaderPrecisionFormat` (en-US)
* `WebGLSync` (en-US)
* `WebGLTexture` (en-US)
* `WebGLTransformFeedback` (en-US)
* `WebGLUniformLocation` (en-US)
* `WebGLVertexArrayObject` (en-US)
* `WebSocket`
* `WebTransport` (en-US)
* `WebTransportBidirectionalStream` (en-US)
* `WebTransportDatagramDuplexStream` (en-US)
* `WebTransportError` (en-US)
* `WebTransportReceiveStream` (en-US)
Experimental
* `WebTransportSendStream` (en-US)
Experimental
* `WGSLLanguageFeatures` (en-US)
Experimental
* `WheelEvent` (en-US)
* `Window`
* `WindowClient` (en-US)
* `WindowControlsOverlay` (en-US)
Experimental
* `WindowControlsOverlayGeometryChangeEvent` (en-US)
Experimental
* `WindowSharedStorage` (en-US)
Experimental
* `Worker`
* `WorkerGlobalScope` (en-US)
* `WorkerLocation` (en-US)
* `WorkerNavigator` (en-US)
* `Worklet` (en-US)
* `WorkletGlobalScope` (en-US)
* `WorkletSharedStorage` (en-US)
Experimental
* `WritableStream` (en-US)
* `WritableStreamDefaultController` (en-US)
* `WritableStreamDefaultWriter` (en-US)

### X

* `XMLDocument`
* `XMLHttpRequest`
* `XMLHttpRequestEventTarget` (en-US)
* `XMLHttpRequestUpload` (en-US)
* `XMLSerializer` (en-US)
* `XPathEvaluator` (en-US)
* `XPathException` (en-US)
* `XPathExpression` (en-US)
* `XPathNSResolver` (en-US)
* `XPathResult` (en-US)
* `XRAnchor` (en-US)
Experimental
* `XRAnchorSet` (en-US)
Experimental
* `XRBoundedReferenceSpace` (en-US)
Experimental
* `XRCompositionLayer` (en-US)
Experimental
* `XRCPUDepthInformation` (en-US)
Experimental
* `XRCubeLayer` (en-US)
Experimental
* `XRCylinderLayer` (en-US)
Experimental
* `XRDepthInformation` (en-US)
Experimental
* `XREquirectLayer` (en-US)
Experimental
* `XRFrame` (en-US)
Experimental
* `XRHand` (en-US)
* `XRHitTestResult` (en-US)
Experimental
* `XRHitTestSource` (en-US)
Experimental
* `XRInputSource` (en-US)
* `XRInputSourceArray` (en-US)
Experimental
* `XRInputSourceEvent` (en-US)
* `XRInputSourcesChangeEvent` (en-US)
* `XRJointPose` (en-US)
* `XRJointSpace` (en-US)
* `XRLayer` (en-US)
Experimental
* `XRLayerEvent` (en-US)
Experimental
* `XRLightEstimate` (en-US)
Experimental
* `XRLightProbe` (en-US)
Experimental
* `XRMediaBinding` (en-US)
Experimental
* `XRPose` (en-US)
* `XRProjectionLayer` (en-US)
Experimental
* `XRQuadLayer` (en-US)
Experimental
* `XRRay` (en-US)
Experimental
* `XRReferenceSpace` (en-US)
* `XRReferenceSpaceEvent` (en-US)
* `XRRenderState` (en-US)
Experimental
* `XRRigidTransform` (en-US)
* `XRSession` (en-US)
Experimental
* `XRSessionEvent` (en-US)
* `XRSpace` (en-US)
* `XRSubImage` (en-US)
Experimental
* `XRSystem` (en-US)
Experimental
* `XRTransientInputHitTestResult` (en-US)
Experimental
* `XRTransientInputHitTestSource` (en-US)
Experimental
* `XRView` (en-US)
Experimental
* `XRViewerPose` (en-US)
* `XRViewport` (en-US)
* `XRWebGLBinding` (en-US)
Experimental
* `XRWebGLDepthInformation` (en-US)
Experimental
* `XRWebGLLayer` (en-US)
Experimental
* `XRWebGLSubImage` (en-US)
Experimental
* `XSLTProcessor`

Veja também
-----------

* Referência de evento de API da Web (en-US)


Uma reintrodução ao JavaScript (Tutorial de JS) - JavaScript

Uma reintrodução ao JavaScript (Tutorial de JS)
===============================================

Introdução
----------

Por que uma reintrodução? Porque JavaScript é conhecida como a mais incompreendida linguagem de programação do mundo. Embora muitas vezes ridicularizada como um brinquedo, por baixo de sua simplicidade enganosa estão alguns recursos poderosos da linguagem, que agora é usado por um número incrível de aplicações de alto nível, mostrando que o conhecimento mais profundo desta tecnologia é uma habilidade importante para qualquer desenvolvedor web, mobile ou desktop.

É sempre bom começar com a história da linguagem. A JavaScript foi criada em 1995 por Brendan Eich, um engenheiro da Netscape, e lançada pela primeira vez com o Netscape 2 no início de 1996. Foi inicialmente chamada de LiveScript, mas logo foi rebatizada, em uma decisão de marketing malfeita, para tentar crescer sobre a popularidade da linguagem Java da Sun Microsystem - apesar das duas terem muito pouco em comum. Esta tem sido uma fonte de confusão desde então.

A Microsoft lançou uma versão compatível com a maior parte da linguagem, chamada de JScript, junto com o IE, três meses mais tarde. A Netscape apresentou a linguagem a Ecma International, uma organização européia de normalização, o que resultou na primeira edição do padrão ECMAScript em 1997. O padrão recebeu uma atualização significativa com o ECMAScript Edição 3 em 1999, e manteve-se praticamente estável desde então. A quarta edição foi abandonada, devido a diferenças políticas relativas à complexidade da linguagem. Muitas partes da quarta edição formam a base da nova edição ECMAScript 5, publicado em dezembro de 2009.

Esta estabilidade foi uma grande notícia para os desenvolvedores, pois isto proporcionou que várias implementações em JavaScript tivessem muito tempo para se firmar. Eu vou focar quase exclusivamente no dialeto da edição 3. Para que seja facil se familiarizar, vou utilizar o termo JavaScript por todo o texto.

Diferentemente da maioria das linguagens de programação , a linguagem JavaScript não possui o conceito de entrada e saída. Ela é projetada para funcionar como uma linguagem de script em um ambiente de terceiros, e cabe ao ambiente fornecer mecanismos para a comunicação com o mundo exterior. O ambiente de terceiros (hospedeiro) mais comum é o navegador, mas interpretadores JavaScript também pode ser encontrados no Adobe Acrobat, Photoshop, imagens SVG, Widget engine do Yahoo! , bem como ambientes de servidor, como Node.js. No entanto, a lista aqui apresentada das áreas nas quais a JavaScript é utilizada é apenas o começo. Ela também inclui bancos de dados NoSQL, como o código-fonte aberto Apache CouchDB, computadores embarcados, ou ambientes de trabalho completos, como o GNOME (um dos GUIs mais populares para os sistemas operacionais GNU / Linux) .

Visão Geral
-----------

A JavaScript é uma linguagem dinâmica orientada a objetos; tem tipos e operadores, objetos e métodos. Sua sintaxe vem das linguagens Java e C, por isso tantas estruturas dessas linguagens se aplicam a JavaScript também. Uma das principais diferenças é que o JavaScript não tem classes; em vez disso, a funcionalidade de classe é realizada por protótipos de objetos. A outra diferença principal é que as funções são objetos, dando as funções a capacidade para armazenar código executável e serem passadas como parametro para qualquer outro objeto.

Vamos começar pelo bloco de construção de qualquer linguagem: os tipos. Programas JavaScript manipulam valores, e esses valores todos pertencem a um tipo. Tipos de JavaScript são :

* números
* strings
* booleanos
* funções
* objetos

... Ops, e o "indefinido" e o "nulo"- , que parecem um pouco estranhos. E arrays (vetores), que são um tipo especial de objeto. E as datas e expressões regulares, que são objetos que você ganha de graça. E para ser tecnicamente preciso, as funções são apenas um tipo especial de objeto. Assim, a lista de tipos se parece mais com isto:

* números (numbers)
* strings (strings)
* booleanos (booleans)
* objetos (objects)
    + funções (functions)
    + vetores (arrays)
    + datas (dates)
    + expressoes regulares (regexp)
* nulo (null)
* indefinido (undefined)

E existem também alguns tipos para erros. As coisas são muito mais fáceis se ficarmos com a primeira lista, no entanto.

Números
-------

Números em JavaScript são "valores de precisão dupla no formato IEEE 754", de acordo com a especificação. Isto tem algumas consequências interessantes. Não existe essa coisa de inteiro em JavaScript, então você deve ser um pouco cuidadoso com seus cálculos se você está acostumado a matemática em C ou Java. Cuidado com coisas como:
```

0.1 + 0.2 == 0.30000000000000004
```

Na prática, valores inteiros são tratados como inteiros de 32 bits (e são armazenados dessa forma em algumas implementações do navegador), que podem ser importantes para as operações bit a bit. Para mais detalhes, consulte The Complete JavaScript Number Reference.

Os operadores numéricos padrões são suportados, incluindo adição, subtração, módulo (ou resto) aritmético e assim por diante. Há também um objeto embutido que eu esqueci de mencionar mais cedo chamado Math para manipular funções e constantes matemáticas mais avançadas:

```js
Math.sin(3.5);
var d = Math.PI \* r \* r;
```

Você pode converter uma string em um inteiro usando a função embutida `parseInt()`. Ela tem um segundo parâmetro opcional para a base da conversão, parâmetro esse que você deveria sempre prover:

```js
> parseInt("123", 10)
123
```

Se você quiser converter um número binário em um inteiro, basta mudar a base:

```js
> parseInt("11", 2)
3
```

Similarmente, você pode fazer a conversão de números de ponto flutuante usando a função embutida `parseFloat()` que usa a base 10 sempre, ao contrário de seu primo `parseInt()`.

Você também pode usar o operador unário `+` para converter valores em números:
```

> + "42"
42
```

Um valor especial chamado `NaN` (sigla de "Not a Number ou Não é Número") é retornado se a string não é um valor numérico:

```js
> parseInt("hello", 10)
NaN
```

`NaN` é tóxico: Se você provê-lo como uma entrada para qualquer operação matemática o resultado também será `NaN`:

```js
> NaN + 5
NaN
```

Você pode testar se é `NaN` usando a função embutida `isNaN()`:

```js
> isNaN(NaN)
true
```

JavaScript também tem os valores especiais `Infinity` e `-Infinity`:

```js
> 1 / 0
Infinity
> -1 / 0
-Infinity
```

Você pode testar se o valor é `Infinity`, `-Infinity` e `NaN` usando a função embutida `isFinite()`:

```js
> isFinite(1/0)
false
> isFinite(-Infinite)
false
> isFinite(NaN)
false
```

**Nota:** As funções `parseInt()` e `parseFloat()` fazem a conversão da string até alcançarem um caracter que não é válido para o formato numérico especificado, então elas retornam o número convertido até aquele ponto. Contudo, o operador "+" simplesmente converte a string em `NaN` se tiver algum caracter inválido nela. Apenas tente por si mesmo converter a string "10.2abc" usando cada um desses métodos no console e entenderá melhor essas diferenças.

Strings
-------

Strings em JavaScript são sequências de caracteres. Para ser mais exato, elas são sequências de Unicode characters, em que cada um deles é representado por um número de 16-bits. Isso deveria ser uma notícia bem-vinda para aqueles que tiveram que lidar com internacionalização.

Se você quiser representar um único caractere, você só tem que usar uma string de tamanho 1.

Para obter o tamanho de uma string, acesse sua propriedade `length`:

```js
> "hello".length
5
```

Essa é nossa primeira pincelada com objetos JavaScript! Eu mencionei que strings também são objetos? De modo que elas têm métodos:

```js
> "hello".charAt(0)
h
> "hello, world".replace("hello", "goodbye")
goodbye, world
> "hello".toUpperCase()
HELLO
```

Outros tipos
------------

No JavaScript há distinção entre `null`, que é um objeto do tipo 'object' para indicar deliberadamente uma ausência de valor, do `undefined`, que é um objeto do tipo 'undefined' para indicar um valor não inicializado — isto é, que um valor não foi atribuído ainda. Vamos falar sobre variáveis depois, mas em JavaScript é possível declarar uma variável sem atribuir um valor para a mesma. Se você fizer isso, a variável será do tipo `undefined`.

JavaScript tem um tipo boolean, ao qual são possíveis os valores `true` e `false` (ambos são palavras-chave). Qualquer valor pode ser convertido em um boolean, de acordo com as seguintes regras:

1. `false`, `0`, a string vazia(`""`), `NaN`, `null`, e `undefined` todos tornam-se `false`
2. todos os outros valores tornam-se `true`

Você pode fazer essa conversão explicitamente usando a função `Boolean()`:

```js
> Boolean("")
false
> Boolean(234)
true
```

Contudo, essa é uma necessidade rara, uma vez que JavaScript silenciosamente fará essa conversão quando for esperado um boolean, como em uma instrução `if`. Por isso, algumas vezes falamos simplesmente em "valores true" e "valores false" nos referindo a valores que se tornaram `true` e `false`, respectivamente, quando convertidos em boolean. Alternativamente, esses valores podem ser chamados de "truthy" (verdade/verdadeiro) e "falsy" (falso/falsidade), respectivamente.

Operações booleanas como `&&` (*and* lógico), `||` (*or* lógico), e `!` (*not* lógico) são suportadas.

Variáveis
---------

Novas variáveis em JavaScript são declaradas usando a palavra-chave `var`:

```js
var a;
var name = "simon";
```

Se você declarar uma variável sem atribuir qualquer valor a ela, seu tipo será `undefined`.

Uma diferença importante de outras linguagens como Java é que em JavaScript, blocos não tem escopo; somente funções tem escopo. De modo que se uma variável é definida usando `var` numa instrução composta (por exemplo dentro de uma estrutura de controle `if`), ela será visível por toda a função.

Obs: A definição de variáveis usando o let foi introduzida no ECMAScript 6. O let permite escopo de bloco, ou seja, é possível definir uma variável em um bloco `if`, e esta variável ter escopo limitado ao bloco `if`- por exemplo.

Operadores
----------

Operadores numéricos de JavaScript são `+`, `-`, `*`, `/` e `%` - que é o operador resto. Valores são atribuídos usando `=`, e temos também as instruções de atribuição compostas, como `+=` e `-=`. Essas são o mesmo que `x = x operador y`.

```js
x += 5;
x = x + 5;
```

Você pode usar `++` e `--` para incrementar ou decrementar respectivamente. Eles podem ser usados como operadores tanto antes como depois.

O operador `+` também faz concatenação de string:

```js
> "hello" + " world"
hello world
```

Se você adicionar uma string a uma número (ou outro valor) tudo será convertido em uma string primeiro. Isso talvez seja uma pegadinha para você:

```js
> "3" + 4 + 5
345
> 3 + 4 + "5"
75
```

Adicionar uma string em branco a algo é uma maneira melhor de fazer a conversão.

Comparações em JavaScript podem ser feitas usando `<`, `>`, `<=` e `>=`. Isso funciona tanto para strings como para números. A igualdade é um pouco menos simples. O operador igual-duplo faz a coersão de tipo se você colocar tipos diferentes, algumas vezes com resultados interessantes:

```js
> "dog" == "dog"
true
> 1 == true
true
```

Para evitar a coersão de tipo, use o operador igual-triplo:

```js
> 1 === true
false
> true === true
true
```

Temos também os operadores `!=` e `!==` .

JavaScript também tem operações de bit-a-bit. Se quiser usá-las, elas estarão lá.

Estruturas de Controle
----------------------

JavaScript tem um conjunto de estruturas de controle similar à outras linguagens na família do C. Instruções condicionais são suportadas pelo `if` e `else`; você pode encadeá-los se quiser:

```js
var name = "kittens";
if (name == "puppies") {
  name += "!";
} else if (name == "kittens") {
  name += "!!";
} else {
  name = "!" + name;
}
name == "kittens!!";
```

JavaScript tem as estruturas de repetição com os laços `while` e `do-while`. O primeiro é bom para repetições básicas; o segundo é para os casos em que você queira que o corpo da repetição seja executado pelo menos uma vez:

```js
while (true) {
  // an infinite loop!
}

var input;
do {
  input = get\_input();
} while (inputIsNotValid(input));
```

O laço `for` do JavaScript é o mesmo que no C e Java: ele lhe permite prover as informações para o seu laço em uma única linha.

```js
for (var i = 0; i < 5; i++) {
  // Will execute 5 times
}
```

Os operadores `&&` e `||` usam a lógica de curto-circuito, o que quer dizer que, o segundo operando ser executado dependerá do primeiro operando. Isso é útil para checagem de objetos null antes de acessar seus atributos:

```js
var name = o && o.getName();
```

Ou para configuração de valores-padrões:

```js
var name = otherName || "default";
```

JavaScript tem um operador ternário para expressões condicionais:

```js
var allowed = age > 18 ? "yes" : "no";
```

A instrução switch pode ser usada para múltiplas ramificações baseadas em um número ou uma string:

```js
switch (action) {
  case "draw":
    drawit();
    break;
  case "eat":
    eatit();
    break;
  default:
    donothing();
}
```

Se você não adicionar a instrução `break`, a execução irá "cair" no próximo nível. Isso é algo que raramente vai querer fazer — de fato vale mais a pena colocar um comentário especificando essa "queda" para o próximo nível, pois isso o ajudará na hora de fazer a depuração de seu código:

```js
switch (a) {
  case 1: // queda
  case 2:
    eatit();
    break;
  default:
    donothing();
}
```

A cláusula default é opcional. Se quiser, pode colocar expressões tanto no switch como nos cases; Comparações acontecem entre os dois usando o operador `===`:

```js
switch (1 + 3) {
  case 2 + 2:
    yay();
    break;
  default:
    neverhappens();
}
```

Objetos
-------

Objetos JavaScript são simplesmente coleções de pares nome-valor. Como tal, eles são similares à:

* Dicionários em Python
* Hashes em Perl e Ruby
* Hash tables em C e C++
* HashMaps em Java
* Vetores associativos em PHP

Esse tipo de estrutura de dados é largamente utilizada, o que atesta sua versatilidade. Uma vez que tudo em JavaScript é um objeto (tipos básicos principais), qualquer programa JavaScript naturalmente envolve uma grande quantidade de buscas em tabelas hash, o que é algo bom, pois elas são bem rápidas!

A parte "name" é uma string JavaScript, enquanto o valor pode ser qualquer valor JavaScript — incluindo mais objetos. Isso permite que você construa estruturas de dados de qualquer complexidade.

Há basicamente duas formas de criar um objeto vazio:

```js
var obj = new Object();
```

e:

```js
var obj = {};
```

Elas são semanticamente equivalentes; a segunda forma é chamada de sintaxe de objeto literal e é mais conveniente. Essa sintaxe é também o coração do formato JSON e deveria ser sempre preferida.

Uma vez criada, as propriedades de um objeto podem novamente ser acessadas de uma das seguintes formas:

```js
obj.name = "Simon";
var name = obj.name;
```

E...

```js
obj["name"] = "Simon";
var name = obj["name"];
```

Estas também são semânticamente equivalentes. A segunda forma tem a vantagem de que o valor da chave é passado através de uma string, que pode ser calculada em tempo de execução, muito embora esse método previna o uso de alguns mecanismos tais como a otimização e a minificação. Outra vantagem é a possibilidade de se atribuir palavras-reservadas aos nomes das propriedades:

```js
obj.for = "Simon"; // Erro de sintaxe, pois 'for' é uma palavra reservada
obj["for"] = "Simon"; // Funciona bem
```

A sintaxe de objeto literal pode ser usada para inicializar completamente um objeto:

```js
var obj = {
  name: "Carrot",
  for: "Max",
  details: {
    color: "orange",
    size: 12,
  },
};
```

O acesso aos atributos podem ser encadeados:

```js
> obj.details.color
orange
> obj["details"]["size"]
12
```

Vetores
-------

Vetores em JavaScript são, de fato, um tipo especial de objeto. Eles funcionam de forma muito similar à objetos regulares (propriedades numéricas podem naturalmente ser acessadas somente usando a sintaxe [], colchetes ), porém eles tem uma propriedade mágica chamada '`length`'. Ela sempre é o maior índice de um vetor mais 1.

A forma tradicional de se criar um vetor em JavaScript é a seguinte:

```js
> var a = new Array();
> a[0] = "dog";
> a[1] = "cat";
> a[2] = "hen";
> a.length
3
```

Existe uma notação mais conveniente usando um vetor literal:

```js
> var a = ["dog", "cat", "hen"];
> a.length
3
```

Deixar uma vírgula à direita no final de um vetor literal gerará inconsistência entre os navegadores, portanto não faça isso.

Note que `array.length` não é necessariamente o número de itens em um vetor. Considere o seguinte:

```js
> var a = ["dog", "cat", "hen"];
> a[100] = "fox";
> a.length
101
```

Lembre-se — o tamanho de um vetor é o maior índice mais 1.

Se você fizer referência a um índice de vetor inexistente, obterá um `undefined`:

```js
> typeof a[90]
undefined
```

Você pode iterar sobre um vetor da seguinte forma:

```js
for (var i = 0; i < a.length; i++) {
  // Faça algo com a[i]
}
```

Isso é um pouco ineficaz visto que você está procurando a propriedade length uma vez a cada iteração. Uma melhoria poderia ser:

```js
for (var i = 0, len = a.length; i < len; i++) {
  // Faça algo com a[i]
}
```

Uma forma mais elegante ainda poderia ser:

```js
for (var i = 0, item; (item = a[i++]); ) {
  // Faça algo com item
}
```

Aqui nós estamos declarando duas variáveis. A atribuição na parte do meio do laço `for` é também testada — se for verdadeira, o laço continuará. Uma vez que o `i` é incrementado toda vez, os itens do array serão atribuídos a variável item sequencialmente. A iteração é finalizada quando item "falsy" é encontrado (tal como o `undefined`, false ou zero).

Note que esse truque só deveria ser usado em vetores que você sabe não conter valores "falsy" (vetores de objeto ou nós DOM por exemplo). Se você iterar sobre dados numéricos que possam ter o 0 ou sobre dados string que possam ter uma string vazia, você deveria usar a segunda forma como alternativa.

Uma outra forma de iterar é usar o laço `for...in`. Note que se alguém adicionou novas propriedades ao `Array.prototype`, elas também podem ser iteradas usando este laço:

```js
for (var i in a) {
  // Do something with a[i]
}
```

Se quiser adicionar um item a um vetor, simplesmente faça desse jeito:

```js
a[a.length] = item; // é o mesmo que a.push(item);
```

Vetores vem com vários métodos:

| Nome do método | Descrição |
| --- | --- |
| `a.toString()` | Retorna uma string com o toString()de cada elemento separado por vírgulas. |
| `a.toLocaleString()` | Retorna uma string com o toLocaleString()de cada elemento separado por vírgulas. |
| `a.concat(item[, itemN])` | Retorna um novo vetor com os itens adicionados nele. |
| `a.join(sep)` | Converte um vetor em uma string com os valores do vetor separados pelo valor do parâmetro sep |
| `a.pop()` | Remove e retorna o último item. |
| `a.push(item[, itemN])` | `Push` adiciona um ou mais itens ao final. |
| `a.reverse()` | Reverte o vetor. |
| `a.shift()` | Remove e retorna o primeiro item. |
| `a.slice(start, end)` | Retorna um sub-vetor. |
| `a.sort([cmpfn])` | Prover uma função opcional para fazer a comparação. |
| `a.splice(start, delcount[, itemN])` | Permite que você modifique um vetor por apagar uma seção e substituí-lo com mais itens. |
| `a.unshift([item])` | Acrescenta itens ao começo do vetor. |

Funções
-------

Junto com objetos, funções são os componentes principais para o entendimento do JavaScript. A função mais básica não poderia ser mais simples:

```js
function add(x, y) {
  var total = x + y;
  return total;
}
```

Isso demonstra tudo o que há para se saber sobre funções básicas. Uma função JavaScript pode ter 0 ou mais parâmetros declarados. O corpo da função pode conter tantas instruções quantas quiser e pode declarar suas próprias variáveis que são de escopo local àquela função. A instrução `return` pode ser usada para retornar um valor em qualquer parte da função, finalizando a função. Se nenhuma instrução de retorno for usada (ou um retorno vazio sem valor), o JavaScript retorna `undefined`.

Os parâmetros nomeados se parecem mais com orientações do que com outra coisa. Você pode chamar a função sem passar o parâmetro esperado, nesse caso eles receberão o valor `undefined`.

```js
> add()
NaN // Você não pode executar adição em undefined
```

Você também pode passar mais argumentos do que a função está esperando:

```js
> add(2, 3, 4)
5 // adicionado os dois primeiros; 4 foi ignorado
```

Pode parecer um pouco bobo, mas no corpo da função você tem acesso a uma variável adicional chamada `arguments`, que é um objeto parecido com um vetor que contém todos os valores passados para a função. Vamos rescrever a função add para tomarmos tantos valores quanto quisermos:

```js
function add() {
    var sum = 0;
    for (var i = 0, j = arguments.length; i < j; i++) {
        sum += arguments[i];
    }
    return sum;
}

> add(2, 3, 4, 5)
14
```

Isso realmente não é muito mais útil do que escrever `2 + 3 + 4 + 5`. Vamos criar uma função para calcular média:

```js
function avg() {
    var sum = 0;
    for (var i = 0, j = arguments.length; i < j; i++) {
        sum += arguments[i];
    }
    return sum / arguments.length;
}
> avg(2, 3, 4, 5)
3.5
```

Isso é muito útil, mas introduz um novo problema. A função `avg()` precisa de uma lista de argumentos separados por vírgula — mas e se o que quiser for procurar a média de um vetor? Você poderia apenas rescrever a função da seguinte forma:

```js
function avgArray(arr) {
    var sum = 0;
    for (var i = 0, j = arr.length; i < j; i++) {
        sum += arr[i];
    }
    return sum / arr.length;
}
> avgArray([2, 3, 4, 5])
3.5
```

Porém, seria legal se pudéssemos reusar a função que já tínhamos criado. Felizmente, JavaScript lhe permite chamar a função, e chamá-la com um conjunto arbitrário de argumentos, usando o método `apply()` presente em qualquer objeto função.

```js
> avg.apply(null, [2, 3, 4, 5])
3.5
```

O segundo argumento do `apply()` é o vetor para usar como argumento; o primeiro será discutido mais tarde. Isso enfatiza o fato que funções também são objetos.

JavaScript lhe permite criar funções anônimas.

```js
var avg = function () {
  var sum = 0;
  for (var i = 0, j = arguments.length; i < j; i++) {
    sum += arguments[i];
  }
  return sum / arguments.length;
};
```

Isso é semanticamente equivalente a forma `function avg()`. É extremamente poderoso como ele lhe permite colocar a definição completa de uma função em qualquer lugar, que você normalmente poria uma expressão. Isso lhe permite todo tipo de truques engenhosos. Aqui está uma maneira de "esconder" algumas variáveis locais — como escopo de bloco em C:

```js
> var a = 1;
> var b = 2;
> (function() {
    var b = 3;
    a += b;
})();
> a
4
> b
2
```

JavaScript lhe permite chamar funções recursivamente. Isso é particularmente útil quando estamos lidando com estruturas de árvore, como quando estavamos navegando no DOM.

```js
function countChars(elm) {
  if (elm.nodeType == 3) {
    // TEXT\_NODE
    return elm.nodeValue.length;
  }
  var count = 0;
  for (var i = 0, child; (child = elm.childNodes[i]); i++) {
    count += countChars(child);
  }
  return count;
}
```

Isso destaca um problema potencial com funções anônimas: Como chamá-las recursivamente se elas não tem um nome? JavaScript lhe permite nomear expressões de função para isso. Você pode usar EFIIs nomeadas (Expressões Funcionais Imediatamente Invocadas), conforme abaixo:

```js
var charsInBody = (function counter(elm) {
  if (elm.nodeType == 3) {
    // TEXT\_NODE
    return elm.nodeValue.length;
  }
  var count = 0;
  for (var i = 0, child; (child = elm.childNodes[i]); i++) {
    count += counter(child);
  }
  return count;
})(document.body);
```

O nome provido para a função anônima conforme acima só é (ou no mínimo só deveria ser) visível ao escopo da própria função. Isso tanto permite que mais otimizações sejam feitas pela engine como deixa o código mais legível.

Objetos Personalizados
----------------------

**Nota:** Para uma discursão mais detalhada de programação orientada a objetos em JavaScript, veja Introdução a JavaScript Orientado a Objeto.

Na clássica Programação Orientada a Objetos, objetos são coleções de dados e métodos que operam sobre esses dados. JavaScript é uma linguagem baseada em protótipos que não contém a estrutura de classe, como tem em C++ e Java. (Algumas vezes isso é algo confuso para o programador acostumado a linguagens com estrutura de classe). Em vez disso, JavaScript usa funções como classes. Vamos considerar um objeto pessoa com os campos primeiro e último nome. Há duas formas em que o nome talvez possa ser exibido: como "primeiro nome segundo nome" ou como "último nome, primeiro nome". Usando as funções e objetos que discutimos anteriormente, aqui está uma forma de fazer isso:

```js
function makePerson(first, last) {
    return {
        first: first,
        last: last
    }
}
function personFullName(person) {
    return person.first + ' ' + person.last;
}
function personFullNameReversed(person) {
    return person.last + ', ' + person.first
}
> s = makePerson("Simon", "Willison");
> personFullName(s)
Simon Willison
> personFullNameReversed(s)
Willison, Simon
```

Isso funciona, mas é muito feio. Você termina com dúzias de funções em seu escopo global. O que nós realmente precisamos é uma forma de anexar uma função a um objeto. Visto que funções são objetos, isso é fácil:

```js
function makePerson(first, last) {
    return {
        first: first,
        last: last,
        fullName: function() {
            return this.first + ' ' + this.last;
        },
        fullNameReversed: function() {
            return this.last + ', ' + this.first;
        }
    }
}
> s = makePerson("Simon", "Willison")
> s.fullName()
Simon Willison
> s.fullNameReversed()
Willison, Simon
```

Há algo aqui que não havíamos visto anteriormente: a palavra-chave '`this`'. Usada dentro de uma função, '`this`' refere-se ao objeto corrente. O que aquilo de fato significa é especificado pelo modo em que você chamou aquela função. Se você chamou-a usando notação ponto ou notação colchete em um objeto, aquele objeto torna-se '`this`'. Se a notação ponto não foi usada pela chamada, '`this`' refere-se ao objeto global. Isso é uma frequente causa de erros. Por exemplo:

```js
> s = makePerson("Simon", "Willison")
> var fullName = s.fullName;
> fullName()
undefined undefined
```

Quando chamamos `fullName()`, '`this`' está ligado ao objeto global. Visto que não há variáveis globais chamadas `first` ou `last` obtemos `undefined` para cada um.

Podemos tirar vantagem da palavra chave '`this`' para melhorar nossa função `makePerson`:

```js
function Person(first, last) {
  this.first = first;
  this.last = last;
  this.fullName = function () {
    return this.first + " " + this.last;
  };
  this.fullNameReversed = function () {
    return this.last + ", " + this.first;
  };
}
var s = new Person("Simon", "Willison");
```

Nós introduzimos uma outra palavra-chave: '`new`'. `new` é fortemente relacionada a '`this`'. O que ele faz é criar um novo objeto vazio, e então chamar a função especificada com '`this`' para atribuir aquele novo objeto. Funções que são desenhadas para ser chamadas pelo '`new`' são chamadas de funções construtoras. Uma prática comum é capitular essas funções como um lembrete de chamá-las com o `new`.

Nossos objetos pessoa estão ficando melhor mas ainda existem algumas arestas feias. Toda vez que criamos um objeto pessoa, criamos duas marcas de nova função dentro dele — não seria melhor se este código fosse compartilhado?

```js
function personFullName() {
  return this.first + " " + this.last;
}
function personFullNameReversed() {
  return this.last + ", " + this.first;
}
function Person(first, last) {
  this.first = first;
  this.last = last;
  this.fullName = personFullName;
  this.fullNameReversed = personFullNameReversed;
}
```

Assim está melhor: estamos criando as funções de método apenas uma vez, e atribuimos referências para elas dentro do construtor. Podemos fazer algo melhor do que isso? A resposta é sim:

```js
function Person(first, last) {
  this.first = first;
  this.last = last;
}
Person.prototype.fullName = function () {
  return this.first + " " + this.last;
};
Person.prototype.fullNameReversed = function () {
  return this.last + ", " + this.first;
};
```

`Person.prototype` é um objeto compartilhado por todas as instâncias de `Person`. Este forma parte da cadeia de buscas (que tem um nome especial, cadeia de protótipos ou "prototype chain"): toda a vez que você tentar acessar uma propriedade de `Person` que não está configurada, Javascript irá verificar em `Person.prototype` para ver se esta propriedade existe por lá. Como resultado, qualquer coisa atribuída à `Person.prototype` torna-se disponível para todas as instâncias deste construtor, através do objeto `this`.

Esta é uma ferramenta incrivelmente poderosa. JavaScript permite a você modificar algo prototipado em qualquer momento no seu programa. Isto significa que você pode adicionar métodos extras para objetos pré-existentes, em tempo de execução:

```js
> s = new Person("Simon", "Willison");
> s.firstNameCaps();
TypeError on line 1: s.firstNameCaps is not a function
> Person.prototype.firstNameCaps = function() {
    return this.first.toUpperCase()
}
> s.firstNameCaps()
SIMON
```

Curiosamente, você pode também adicionar coisas para o protótipo de objetos built-in de Javascript. Vamos adicionar um método para `String` que retorna a string invertida:

```js
> var s = "Simon";
> s.reversed()
TypeError on line 1: s.reversed is not a function
> String.prototype.reversed = function() {
    let start = 0, end = this.length - 1
    result = new Array(this.length)
    while(start <= end) {
      result[start] = this[end]
      result[end] = this[start]
      start++, end--
    }
    return result.join('')
}
> s.reversed()
nomiS
```

Nosso novo método funciona inclusive em string literais!

```js
> "This can now be reversed".reversed()
desrever eb won nac sihT
```

Como antes mencionado, o protótipo forma parte de uma cadeia. A raiz dessa cadeia é `Object.prototype`, dos quais inclui o método `toString()` — este é o método que é chamado quando você tenta representar um objeto como uma string. Isto é útil para depurar os nossos objetos `Person`:

```js
> var s = new Person("Simon", "Willison");
> s
[object Object]
> Person.prototype.toString = function() {
    return '<Person: ' + this.fullName() + '>';
}
> s
<Person: Simon Willison>
```

Lembra como `avg.apply()` tinha um primeiro argumento null? Nós podemos revisitar isto, agora. O primeiro argumento para `apply()` é o objeto que deve ser tratado como '`this`'. Por exemplo, aqui está uma implementação trivial de '`new`':

```js
function trivialNew(constructor, ...args) {
  var o = {}; // Create an object
  constructor.apply(o, args);
  return o;
}
```

Isto não é exatamente uma réplica de `new` porque não configura a cadeia de protótipos. `apply()` é difícil de ilustrar — não é algo que você usa com frequência, mas é útil conhecer a respeito. No código acima, `...args` é chamado de "argumentos rest" — como o nome indica, isto contém o restante dos parâmetros.

Ao chamar

```js
var bill = trivialNew(Person, "Willian", "Orange");
```

é equivalente a

```js
var bill = new Person("Willian", "Orange");
```

`apply()` tem uma função irmã de nome `call`, que novamente permite você configurar o '`this`' mas toma uma lista expandida de argumentos, ao invés de um array.

```js
function lastNameCaps() {
  return this.last.toUpperCase();
}
var s = new Person("Simon", "Willison");
lastNameCaps.call(s);
// Is the same as:
s.lastNameCaps = lastNameCaps;
s.lastNameCaps();
```

Funções Internas
----------------

Em JavaScript é permitido declarar uma função dentro de outras funções. Nós já vimos isso antes, com uma versão preliminar da função `makePerson()`. Um detalhe importante sobre funções aninhadas em JavaScript é que elas podem acessar as variáveis do escopo das funções parente:

```js
function parentFunc() {
  var a = 1;

  function nestedFunc() {
    var b = 4; // parentFunc can't use this
    return a + b;
  }
  return nestedFunc(); // 5
}
```

Isto permite um compromisso maior de utilidade ao escrever um código de melhor mantenibilidade. Se uma função depende de uma ou mais funções que não são úteis para outras parte do seu código, você pode aninhar estas funções utilitárias dentro da função que será chamada. Isto mantém o número de funções que estão no escopo global baixo, o que é sempre uma boa coisa.

Isto é também um ótimo contador de atração de variáveis globais. Quando se escreve um código complexo, é sempre tentador usar as variáveis globais para compartilhar valores entre múltiplas funções — do qual leva a um código que é difícil de manter. Funções aninhadas podem compartilhar variáveis em seus parentes, então você pode usar este mecanismo para acoplar e juntar funções, quando isto fizer sentido, sem poluir o seu "namespace" global — 'globais locais' se preferir. Esta técnica deve ser usada com cautela, mas é uma habilidade a se ter.

Clausuras (Closures)
--------------------

Isto nos leva a uma das abstrações mais poderosas que JavaScript tem a oferecer — mas também a mais potencionalmente confusa. O que isto faz?

```js
function makeAdder(a) {
  return function (b) {
    return a + b;
  };
}
var x = makeAdder(5);
var y = makeAdder(20);
x(6); // ?
y(7); // ?
```

O nome da função `makeAdder` já diz tudo: ela cria novas funções 'adder', na qual, quando chamada com um argumento, adiciona o argumento com a que foi criada.

O que está acontecendo aqui é muito parecido com o que estava acontencedo com as funções internas vistas anterioremente: uma função definida dentro de uma outra função tem acessso às variáveis da função de fora. A única diferença aqui é que a função de fora retornou e, como consequência do senso comum, deve dizer que todas as variáveis locais não existem mais. Mas elas *ainda* existem — caso contrário a função adicionadora não seria capaz de funcionar. Mais ainda, há duas "cópias" diferentes de variáveis locais para `makeAdder` — uma na qual o `a` é 5 e a outra na qual `a` é 20. Então, o resultado dessas chamadas de funções é o seguinte:

```js
x(6); // returns 11
y(7); // returns 27
```

Eis o que acontece na verdade: sempre que o JavaScript executa uma função, um objeto de 'escopo' é criado para guardar as variáveis locais criadas dentro desta função. Ela é inicializada com quaisquer variáveis passadas como parâmetros da função. Isto é similar ao objeto global, em que todas as variáveis globais e funções vivem, mas com algumas diferenças importantes: primeiro, um novo objeto de escopo é criado toda a vez que uma função começa a executar, e segundo, diferente do objeto global (que nos navegadores é acessado com `window`) estes objetos não podem ser diretamente acessados através do seu código JavaScript. Não há nenhum mecanismo para iterar sobre as propriedades do escopo corrente do objeto, por exemplo.

Então, quando `makeAdder` é chamado, um objeto de escopo é criado com uma única propriedade: `a`, a qual é o argumento passado para a função `makeAdder`. `makeAdder` então retorna uma nova função criada. Normalmente o coletor de lixo de JavaScript poderia limpar o objeto de escopo criado para `makeAdder` neste ponto, mas a função de retorno mantém uma referência ao objeto de escopo. Como resultado, o objeto de escopo não será coletado como lixo até que não haja mais referências para função objeto que `makeAdder` retornou.

Objetos de escopo formam uma cadeia chamada de cadeia de escopos, similar a cadeia de protótipos usadas no sistema de objetos de JavaScript.

Uma clausura é a combinação de uma função e o objeto de escopo na qual é criado. Clausuras permitem você guardar estado — de tal forma, elas podem ser frequentemente utilizadas no lugar de objetos.


Enumerabilidade e posse de propriedades - JavaScript

Enumerabilidade e posse de propriedades
=======================================

 Propriedades enumeráveis são aquelas propriedades cuja flag interna [[Enumerable]] é verdadeira (true), que é o padrão para propriedades criadas via assinatura simples ou através de um inicializador (propriedades definidas através de Object.defineProperty e tipo padrão [[Enumerable]] falso (false)).Propriedades enumeráveis aparecem em for...in loops exceto se o nome da propriedade for um objeto Symbol. Posse de propriedades é determinada pelo fato da propriedade pertencer ao objeto diretamente e não a uma cadeira de protótipos. Propriedades de um objeto pode também ser recuperadas diretamente. Há um número de built-in de detecção, iteração/enumeração e recuperação de propriedades, com o gráfico mostrando que estão disponíveis.O código de exemplo a seguir demostra como obter as categorias que faltam.

 Propriedade de enumerabilidade e posse - métodos internos de detecção,
 recuperação, e iteração
 | Funcionalidade | Próprio objeto | Próprio objeto e sua cadeia de caracteres | Somente cadeia de protótipos |
| --- | --- | --- | --- |
| Detecção |

| Enumerável | Não enumerável | Enumerável e Não enumerável |
| --- | --- | --- |
| `propertyIsEnumerable (en-US)` | `hasOwnProperty`
 e não
 `propertyIsEnumerable (en-US)` | `hasOwnProperty` |

 | Não disponível sem código extra | Não disponível sem código extra |
| Recuperação |

| Enumerável | Não enumerável | Enumerável e Não enumerável |
| --- | --- | --- |
| `Object.keys (en-US)` | `getOwnPropertyNames (en-US)`
 filtrou-se para incluir as propriedades quando não passado
 `propertyIsEnumerable (en-US)` | `getOwnPropertyNames (en-US)` |

 | Não disponível sem código extra | Não disponível sem código extra |
| Iteração |

| Enumerável | Não enumerável | Enumerável e Não enumerável |
| --- | --- | --- |
|
 Iterar
 `Object.keys (en-US)` |
 itera
 `getOwnPropertyNames (en-US)` filtrou-se para incluir as propriedades quando não passado
 `propertyIsEnumerable (en-US)`
 | `iterargetOwnPropertyNames (en-US)` |

 |

| Enumerável | Não enumerável | Enumerável e Não enumerável |
| --- | --- | --- |
| `for..in (en-US)` | Não disponível sem código extra | Não disponível sem código extra |

 | Não disponível sem código extra |

Obtendo propriedades por enumerabilidade/posse
----------------------------------------------

Note que não é o algoritmo mais eficiente para todos os casos, mas útil para uma demonstração rápida.

* Detecção pode ocorrer por `SimplePropertyRetriever.theGetMethodYouWant(obj).indexOf(prop) > -1`
* Iteração pode ocorrer por `SimplePropertyRetriever.theGetMethodYouWant(obj).forEach(function (value, prop) {});` (ou use `filter()`, `map()`, etc.)

```js
var SimplePropertyRetriever = {
  getOwnEnumerables: function (obj) {
    return this.\_getPropertyNames(obj, true, false, this._enumerable);
    // Ou poderia usar for..in filtrado com hasOwnProperty ou apenas isto: return Object.keys(obj);
  },
  getOwnNonenumerables: function (obj) {
    return this.\_getPropertyNames(obj, true, false, this._notEnumerable);
  },
  getOwnEnumerablesAndNonenumerables: function (obj) {
    return this.\_getPropertyNames(
      obj,
      true,
      false,
      this._enumerableAndNotEnumerable,
    );
    // Ou apenas use: return Object.getOwnPropertyNames(obj);
  },
  getPrototypeEnumerables: function (obj) {
    return this.\_getPropertyNames(obj, false, true, this._enumerable);
  },
  getPrototypeNonenumerables: function (obj) {
    return this.\_getPropertyNames(obj, false, true, this._notEnumerable);
  },
  getPrototypeEnumerablesAndNonenumerables: function (obj) {
    return this.\_getPropertyNames(
      obj,
      false,
      true,
      this._enumerableAndNotEnumerable,
    );
  },
  getOwnAndPrototypeEnumerables: function (obj) {
    return this.\_getPropertyNames(obj, true, true, this._enumerable);
    // Ou poderia usar filtrado for..in
  },
  getOwnAndPrototypeNonenumerables: function (obj) {
    return this.\_getPropertyNames(obj, true, true, this._notEnumerable);
  },
  getOwnAndPrototypeEnumerablesAndNonenumerables: function (obj) {
    return this.\_getPropertyNames(
      obj,
      true,
      true,
      this._enumerableAndNotEnumerable,
    );
  },
  // Private static property checker callbacks
  \_enumerable: function (obj, prop) {
    return obj.propertyIsEnumerable(prop);
  },
  \_notEnumerable: function (obj, prop) {
    return !obj.propertyIsEnumerable(prop);
  },
  \_enumerableAndNotEnumerable: function (obj, prop) {
    return true;
  },
  // Inspirado por http://stackoverflow.com/a/8024294/271577
  \_getPropertyNames: function getAllPropertyNames(
    obj,
 iterateSelfBool,
 iteratePrototypeBool,
 includePropCb,
  ) {
    var props = [];

    do {
      if (iterateSelfBool) {
        Object.getOwnPropertyNames(obj).forEach(function (prop) {
          if (props.indexOf(prop) === -1 && includePropCb(obj, prop)) {
            props.push(prop);
          }
        });
      }
      if (!iteratePrototypeBool) {
        break;
      }
      iterateSelfBool = true;
    } while ((obj = Object.getPrototypeOf(obj)));

    return props;
  },
};
```

Tabela de Detecção
------------------

|  | `in` | `for..in` | `hasOwnProperty` | `propertyIsEnumerable` | `in Object.keys` | `in Object.getOwnPropertyNames` | in Object.getOwnPropertyDescriptors |
| --- | --- | --- | --- | --- | --- | --- | --- |
| Enumerável | true | true | true | true | true | true | true |
| Não enumerável | true | false | true | false | false | true | true |
| Inherited Enumerable | true | true | false | false | false | false | false |
| Inherited Nonenumerable | true | false | false | false | false | false | false |
| Account for Symbols keys | true | false | true | true | false | false | true |

Veja também
-----------

* `in` (en-US)
* `for..in` (en-US)
* `hasOwnProperty`
* `propertyIsEnumerable` (en-US)
* `getOwnPropertyNames` (en-US)
* `Object.keys` (en-US)
* `Object.getOwnPropertyDescriptors`


Closures - JavaScript

Closures
========

Uma **closure** é a combinação de uma função com as referências ao estado que a circunda (o **ambiente léxico**). Em outras palavras, uma closure lhe dá acesso ao escopo de uma função externa a partir de uma função interna. Em JavaScript, as closures são criadas toda vez que uma função é criada, no momento da criação da função.

Escopo léxico
-------------

Considere a função abaixo:

```js
function init() {
  var name = "Mozilla"; // name é uma variável local criada pelo init
  function displayName() {
    // displayName() é a função interna, uma closure
    console.log(name); // usa a variável declarada na função pai
  }
  displayName();
}
init();
```

A função `init()` cria uma variável local chamada `name`, e depois define uma função chamada `displayName()`. `displayName()` é uma função aninhada (uma *closure*) — ela é definida dentro da função `init()`, e está disponivel apenas dentro do corpo daquela função. Diferente de init(), `displayName()` não tem variáveis locais próprias, e ao invés disso reusa a variável `name` declarada na função pai.

Rode o código e veja que isso funciona. Este é um exemplo de *escopo léxico:* em JavaScript, o escopo de uma variável é definido por sua localização dentro do código fonte (isto é aparentemente *léxico*) e funções aninhadas têm acesso às variáveis declaradas em seu escopo externo.

Closure
-------

Agora considere o seguinte exemplo:

```js
function makeFunc() {
  var name = "Mozilla";
  function displayName() {
    alert(name);
  }
  return displayName;
}

var myFunc = makeFunc();
myFunc();
```

Se você rodar este código o mesmo terá exatamente o mesmo efeito que o `init()` do exemplo anterior: a palavra "Mozilla" será mostrada na caixa de alerta. O que é diferente - e interessante - é o fato de que a função interna do `displayName()` foi retornada da função externa antes de ser executada.

Pode parecer não muito intuitivo de que o código de fato funciona. Normalmente variáveis locais de uma função, apenas existem pela duração de sua execução. Uma vez que `makeFunc()` terminou de executar, é razoável esperar que a variável `name` não será mais necessária. Dado que o código ainda funciona como o esperado, este não é o caso.

A solução para tal problema é que a função `myFunc` tornou-se uma `closure`. Uma closure trata-se de um tipo especial de objeto que combina duas coisas: a função e o ambiente onde a função foi criada. Este ambiente consiste de quaisquer variáveis que estavam no escopo naquele momento em que a função foi criada. Neste caso, `myFunc` é a closure que incorpora tanto a função `displayName` quanto a palavra *Mozilla* que existia quando a closure foi criada.

Aqui temos um exemplo um pouco mais interessante, a função `makeAdder`:

```js
function makeAdder(x) {
  return function (y) {
    return x + y;
  };
}

var add5 = makeAdder(5);
var add10 = makeAdder(10);

print(add5(2)); // 7
print(add10(2)); // 12
```

Neste exemplo definimos a função `makeAdder(x)` que toma um único argumento `x` e retorna uma nova função. A função retornada toma então um único argumento, `y`, e retorna então a soma de `x` e de `y`.

Na essência o `makeAdder` trata-se de uma *função fábrica -* irá construir outras funções que podem adicionar um determinado valor específico a seu argumento. No exemplo acima usamos a fábrica de funções para criar duas novas funções - uma que adiciona 5 ao argumento, e outra que adiciona 10.

Ambas as funções `add5` e `add10` são closures. Compartilham o mesmo corpo de definição de função mas armazenam diferentes ambientes. No ambiente da `add5`, por exemplo, `x` equivale a 5, enquanto na `add10` o valor de x é 10.

Closures na prática
-------------------

Esta é a teoria — mas closures são realmente úteis? Vamos considerar suas aplicações práticas. Uma closure deixa você associar dados (do ambiente) com uma função que trabalha estes dados. Isto está diretamente ligado com programação orientada a objetos, onde objetos nos permitem associar dados (as propriedades do objeto) utilizando um ou mais métodos.

Consequentemente, você pode utilizar uma closure em qualquer lugar onde você normalmente utilizaria um objeto de único método.

Situações onde você poderia utilizar isto são comuns em ambientes web. Muitos códigos escritos em JavaScript para web são baseados em eventos - nós definimos algum comportamento e então, o atribuimos a um evento que será disparado pelo usuário (quando uma tecla for pressionada, por exemplo). Nosso código normalmente é utilizado como callback: uma função que será executada como resposta ao evento.

Aqui temos um exemplo prático: suponha que queremos adicionar alguns botões para ajustar o tamanho do texto de uma página. Um jeito de fazer seria especificar o tamanho da fonte no elemento body e então definir o tamanho dos outros elementos da página (os cabeçalhos, por exemplo) utilizando a unidade relativa em:

```css
body {
  font-family: Helvetica, Arial, sans-serif;
  font-size: 12px;
}

h1 {
  font-size: 1.5em;
}
h2 {
  font-size: 1.2em;
}
```

Nossos botões interativos de tamanho de texto podem alterar a propriedade font-size do elemento body, e os ajustes serão refletidos em outros elementos graças à unidade relativa.

O código JavaScript:

```js
function makeSizer(size) {
  return function () {
    document.body.style.fontSize = size + "px";
  };
}

var size12 = makeSizer(12);
var size14 = makeSizer(14);
var size16 = makeSizer(16);
```

`size12`, `size14` e `size16` agora são funções que devem redimensionar o texto do elemento body para 12, 14 e 16 pixels respectivamente. Nós podemos designá-las a botões (neste caso, links) como feito a seguir:

```js
document.getElementById("size-12").onclick = size12;
document.getElementById("size-14").onclick = size14;
document.getElementById("size-16").onclick = size16;
```

```html
<a href="#" id="size-12">12</a>
<a href="#" id="size-14">14</a>
<a href="#" id="size-16">16</a>
```

View on JSFiddle

Emulando métodos privados com closures
--------------------------------------

Linguagens como Java oferecem a habilidade de declarar métodos privados, o que significa que eles só poderão ser chamados por outros métodos na mesma classe.

O JavaScript não oferece uma maneira nativa de fazer isso, mas é possível emular métodos privados usando closures. Métodos privados não são somente úteis para restringir acesso ao código: eles também oferecem uma maneira eficaz de gerenciar seu namespace global, evitando que métodos não essenciais baguncem a interface pública do seu código.

Veja como definir algumas funções públicas que acessam funções e variáveis privadas, usando closures que também é conhecido como module pattern:

```js
var Counter = (function () {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment: function () {
      changeBy(1);
    },
    decrement: function () {
      changeBy(-1);
    },
    value: function () {
      return privateCounter;
    },
  };
})();

alert(Counter.value()); /\* Alerts 0 \*/
Counter.increment();
Counter.increment();
alert(Counter.value()); /\* Alerts 2 \*/
Counter.decrement();
alert(Counter.value()); /\* Alerts 1 \*/
```

Tem muita coisa acontecendo aqui. Nos exemplos anteriores cada closure teve o seu próprio ambiente; aqui nós criamos um ambiente único que é compartilhado por três funções: `Counter.increment`, `Counter.decrement` e `Counter.value`.

O ambiente compartilhado é criado no corpo de uma função anônima, da qual é executada assim que é definida. O ambiente contém dois itens privados: uma variável chamada `privateCounter` e uma função chamada `changeBy`. Nenhum desses itens privados podem ser acessados diretamente de fora da função anônima. Ao invés disso, eles devem ser acessados pelas três funções públicas que são retornadas.

Aquelas três funções públicas são closures que compartilham o mesmo ambiente. Graças ao escopo léxico do JavaScript, cada uma delas tem acesso a variável `privateCounter` e à função `changeBy`.

**Nota:** Você perceberá que estamos definindo uma função anônima que cria um contador , e então o executamos imediatamente e atribuímos o resultado à variável `Counter`. Poderíamos armazenar essa função em uma variável separada e usá-la para criar diversos contadores.

```js
var makeCounter = function () {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment: function () {
      changeBy(1);
    },
    decrement: function () {
      changeBy(-1);
    },
    value: function () {
      return privateCounter;
    },
  };
};

var Counter1 = makeCounter();
var Counter2 = makeCounter();
alert(Counter1.value()); /\* Alerts 0 \*/
Counter1.increment();
Counter1.increment();
alert(Counter1.value()); /\* Alerts 2 \*/
Counter1.decrement();
alert(Counter1.value()); /\* Alerts 1 \*/
alert(Counter2.value()); /\* Alerts 0 \*/
```

Observe como cada um dos contadores mantém a sua independência em relação ao outro. Seu ambiente durante a execução da função `makeCounter()` é diferente a cada vez que ocorre. A variável `privateCounter` contém uma instância diferente a cada vez.

**Nota:** Usar closures desta maneira oferece uma série de benefícios que estão normalmente associados a programação orientada a objetos, em particular encapsulamento e ocultação de dados.

Criando closures dentro de loops: Um erro comum
-----------------------------------------------

Antes da introdução da palavra chave `let` no JavaScript 1.7, um problema comum ocorria com closures quando eram criadas dentro de um loop. Considere o exemplo:

```html
<p id="help">Notas úteis aparecerão aqui</p>
<p>E-mail: <input type="text" id="email" name="email" /></p>
<p>Nome: <input type="text" id="name" name="name" /></p>
<p>Idade: <input type="text" id="age" name="age" /></p>
```

```js
function showHelp(help) {
  document.getElementById("help").innerHTML = help;
}

function setupHelp() {
  var helpText = [
    { id: "email", help: "Seu e-mail" },
    { id: "name", help: "Seu nome completo" },
    { id: "age", help: "Sua idade (você deve ter mais de 16 anos)" },
  ];

  for (var i = 0; i < helpText.length; i++) {
    // O culpado é o uso do `var` nesta linha
    var item = helpText[i];
    document.getElementById(item.id).onfocus = function () {
      showHelp(item.help);
    };
  }
}

setupHelp();
```

View on JSFiddle

O array `helpText` define três dicas úteis, cada uma associada ao ID de um input no documento. O loop percorre essas definições, atrelando um evento `onfocus` para cada um que mostra o método de ajuda associado.

Se você tentar executar esse código, Você verá que não vai funcionar como esperado. Não importa em qual campo ocorre o focus, a mensagem sobre a sua idade será mostrada.

O motivo disto é que as funções atreladas ao `onfocus` são closures; elas consistem na definição da função e do ambiente capturado do escopo da função `setupHelp`. Três closures foram criados, mas todos eles compartilham o mesmo ambiente. No momento em que os callbacks do `onfocus` são executados, o loop segue seu curso e então a variável `item` (compartilhada por todos os três closures) fica apontando para a última entrada na lista `helpText`.

Uma solução seria neste caso usar mais closures: em particular, usar uma fábrica de funções como descrito anteriormente:

```js
function showHelp(help) {
  document.getElementById("help").textContent = help;
}

function makeHelpCallback(help) {
  return function () {
    showHelp(help);
  };
}

function setupHelp() {
  var helpText = [
    { id: "email", help: "Seu e-mail" },
    { id: "name", help: "Seu nome completo" },
    { id: "age", help: "Sua idade (você deve ter mais de 16 anos)" },
  ];

  for (var i = 0; i < helpText.length; i++) {
    var item = helpText[i];
    document.getElementById(item.id).onfocus = makeHelpCallback(item.help);
  }
}

setupHelp();
```

View on JSFiddle

Isto funciona conforme o esperado. Ao invés dos callbacks compartilharem o mesmo ambiente, a função `makeHelpCallback` cria um novo ambiente para cada um no qual `help` se refere à string correspondente do array `helpText`.

Uma outra maneira de escrever o mesmo usando closures anônimas é:

```js
function showHelp(help) {
  document.getElementById("help").textContent = help;
}

function setupHelp() {
  var helpText = [
    { id: "email", help: "Seu e-mail" },
    { id: "name", help: "Seu nome completo" },
    { id: "age", help: "Sua idade (você deve ter mais de 16 anos)" },
  ];

  for (var i = 0; i < helpText.length; i++) {
    (function () {
      var item = helpText[i];
      document.getElementById(item.id).onfocus = function () {
        showHelp(item.help);
      };
    })(); // Expressão de função invocada imediatamente com o valor atual do item (preservado até a iteração).
  }
}

setupHelp();
```

Se você não quiser usar mais closures, você pode usar a palavra-chave `let` ou `const`:

```js
function showHelp(help) {
  document.getElementById("help").textContent = help;
}

function setupHelp() {
  var helpText = [
    { id: "email", help: "Seu e-mail" },
    { id: "name", help: "Seu nome completo" },
    { id: "age", help: "Sua idade (você deve ter mais de 16 anos)" },
  ];

  for (let i = 0; i < helpText.length; i++) {
    const item = helpText[i];
    document.getElementById(item.id).onfocus = () => {
      showHelp(item.help);
    };
  }
}

setupHelp();
```

Este exemplo usa `const` em vez de `var`, portanto cada closure vincula a variável com escopo de bloco, o que significa que nenhuma closure adicional é necessária.

Outra alternativa poderia ser usar `forEach()` para iterar sobre o array `helpText` e anexar um ouvinte a cada `<input>`, conforme mostrado:

```js
function showHelp(help) {
  document.getElementById("help").textContent = help;
}

function setupHelp() {
  var helpText = [
    { id: "email", help: "Seu e-mail" },
    { id: "name", help: "Seu nome completo" },
    { id: "age", help: "Sua idade (você deve ter mais de 16 anos)" },
  ];

  helpText.forEach(function (text) {
    document.getElementById(text.id).onfocus = function () {
      showHelp(text.help);
    };
  });
}

setupHelp();
```

Considerações de performance
----------------------------

Não é sábio criar funções dentro de outras funções se a closure não for necessário para uma tarefa em particular, pois ele afetará a performance do script de forma bem negativa tanto em velocidade de processamento quanto em consumo de memória.

Por exemplo, ao criar uma nova classe/objeto, os métodos devem normalmente estar associados ao protótipo do objeto do que definido no construtor. O motivo disso é que sempre que o construtor for chamado os métodos serão reatribuídos (isto é, para cada criação de objeto).

Considere o seguinte exemplo pouco prático porém demonstrativo:

```js
function MyObject(name, message) {
  this.name = name.toString();
  this.message = message.toString();
  this.getName = function () {
    return this.name;
  };

  this.getMessage = function () {
    return this.message;
  };
}
```

O código anterior não aproveita os benefícios dos closures e portanto poderia ser reformulado assim:

```js
function MyObject(name, message) {
  this.name = name.toString();
  this.message = message.toString();
}
MyObject.prototype = {
  getName: function () {
    return this.name;
  },
  getMessage: function () {
    return this.message;
  },
};
```

Ou assim:

```js
function MyObject(name, message) {
  this.name = name.toString();
  this.message = message.toString();
}
MyObject.prototype.getName = function () {
  return this.name;
};
MyObject.prototype.getMessage = function () {
  return this.message;
};
```

Nos dois exemplos anteriores, o protótipo herdado pode ser compartilhado por todos os objetos, e as definições de métodos não precisam ocorrer sempre que o objeto for criado. Veja Detalhes do modelo de objeto (en-US) para mais detalhes.