diff --git a/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift b/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift
index b9d8d520..2d6fc33b 100644
--- a/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift
+++ b/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift
@@ -79,6 +79,11 @@ public class JSTypedArray<Element>: JSBridgedClass, ExpressibleByArrayLiteral wh
         Int(jsObject["byteLength"].number!)
     }
 
+    /// Length (in elements) of the typed array.
+    public var length: Int {
+        Int(jsObject["length"].number!)
+    }
+
     /// Calls the given closure with a pointer to a copy of the underlying bytes of the
     /// array's storage.
     ///
@@ -93,18 +98,10 @@ public class JSTypedArray<Element>: JSBridgedClass, ExpressibleByArrayLiteral wh
     ///   argument is valid only for the duration of the closure's execution.
     /// - Returns: The return value, if any, of the `body` closure parameter.
     public func withUnsafeBytes<R>(_ body: (UnsafeBufferPointer<Element>) throws -> R) rethrows -> R {
-        let bytesLength = lengthInBytes
-        let rawBuffer = UnsafeMutableBufferPointer<UInt8>.allocate(capacity: bytesLength)
-        defer { rawBuffer.deallocate() }
-        let baseAddress = rawBuffer.baseAddress!
-        swjs_load_typed_array(jsObject.id, baseAddress)
-        let length = bytesLength / MemoryLayout<Element>.size
-        let rawBaseAddress = UnsafeRawPointer(baseAddress)
-        let bufferPtr = UnsafeBufferPointer<Element>(
-            start: rawBaseAddress.assumingMemoryBound(to: Element.self),
-            count: length
-        )
-        let result = try body(bufferPtr)
+        let buffer = UnsafeMutableBufferPointer<Element>.allocate(capacity: length)
+        defer { buffer.deallocate() }
+        copyMemory(to: buffer)
+        let result = try body(UnsafeBufferPointer(buffer))
         return result
     }
 
@@ -124,21 +121,22 @@ public class JSTypedArray<Element>: JSBridgedClass, ExpressibleByArrayLiteral wh
     /// - Returns: The return value, if any, of the `body`async closure parameter.
     @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
     public func withUnsafeBytesAsync<R>(_ body: (UnsafeBufferPointer<Element>) async throws -> R) async rethrows -> R {
-        let bytesLength = lengthInBytes
-        let rawBuffer = UnsafeMutableBufferPointer<UInt8>.allocate(capacity: bytesLength)
-        defer { rawBuffer.deallocate() }
-        let baseAddress = rawBuffer.baseAddress!
-        swjs_load_typed_array(jsObject.id, baseAddress)
-        let length = bytesLength / MemoryLayout<Element>.size
-        let rawBaseAddress = UnsafeRawPointer(baseAddress)
-        let bufferPtr = UnsafeBufferPointer<Element>(
-            start: rawBaseAddress.assumingMemoryBound(to: Element.self),
-            count: length
-        )
-        let result = try await body(bufferPtr)
+        let buffer = UnsafeMutableBufferPointer<Element>.allocate(capacity: length)
+        defer { buffer.deallocate() }
+        copyMemory(to: buffer)
+        let result = try await body(UnsafeBufferPointer(buffer))
         return result
     }
     #endif
+
+    /// Copies the contents of the array to the given buffer.
+    ///
+    /// - Parameter buffer: The buffer to copy the contents of the array to.
+    ///   The buffer must have enough space to accommodate the contents of the array.
+    public func copyMemory(to buffer: UnsafeMutableBufferPointer<Element>) {
+        precondition(buffer.count >= length, "Buffer is too small to hold the contents of the array")
+        swjs_load_typed_array(jsObject.id, buffer.baseAddress!)
+    }
 }
 
 // MARK: - Int and UInt support
diff --git a/Tests/JavaScriptKitTests/JSTypedArrayTests.swift b/Tests/JavaScriptKitTests/JSTypedArrayTests.swift
index dcc5fb26..0465b1e4 100644
--- a/Tests/JavaScriptKitTests/JSTypedArrayTests.swift
+++ b/Tests/JavaScriptKitTests/JSTypedArrayTests.swift
@@ -109,4 +109,18 @@ final class JSTypedArrayTests: XCTestCase {
             XCTAssertEqual(typedArray[i], Float32(i))
         }
     }
+
+    func testCopyMemory() {
+        let array = JSTypedArray<Int>(length: 100)
+        for i in 0..<100 {
+            array[i] = i
+        }
+        let destination = UnsafeMutableBufferPointer<Int>.allocate(capacity: 100)
+        defer { destination.deallocate() }
+        array.copyMemory(to: destination)
+
+        for i in 0..<100 {
+            XCTAssertEqual(destination[i], i)
+        }
+    }
 }