日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 综合教程 >内容正文

综合教程

浅析Uint8Array语法及常见使用、Uint8Array.slice与Uint8Array.subarray区别(是否指向同一个内存空间)、new Uint8Array(typedArray)构造函数对typedArray的引用问题(保持同一个引用)、Uint8Array与String互相转换

發(fā)布時(shí)間:2023/12/13 综合教程 31 生活家

一、Uint8Array 介紹

  Uint8Array 數(shù)組類型表示一個(gè)8位無(wú)符號(hào)整型數(shù)組,創(chuàng)建時(shí)內(nèi)容被初始化為0。創(chuàng)建完后,可以以對(duì)象的方式或使用數(shù)組下標(biāo)索引的方式引用數(shù)組中的元素。

  詳細(xì)介紹見(jiàn) MDN 描述:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array

  我們要使用了解的話,主要看下示例代碼:

// 來(lái)自長(zhǎng)度
var uint8 = new Uint8Array(2);
uint8[0] = 42;
console.log(uint8[0]); // 42
console.log(uint8.length); // 2
console.log(uint8.BYTES_PER_ELEMENT); // 1

// 來(lái)自數(shù)組
var arr = new Uint8Array([21,31]);
console.log(arr[1]); // 31

// 來(lái)自另一個(gè) TypedArray
var x = new Uint8Array([21, 31]);
var y = new Uint8Array(x);
console.log(y[0]); // 21

// 來(lái)自 ArrayBuffer
var buffer = new ArrayBuffer(8);
var z = new Uint8Array(buffer, 1, 4);
z; // Uint8Array(4)[0, 0, 0, 0] // 來(lái)自一個(gè)迭代器 var iterable = function*(){ yield* [1,2,3]; }(); var uint8 = new Uint8Array(iterable); // Uint8Array[1, 2, 3]

二、Uint8Array.slice 與 Uint8Array.subarray 區(qū)別

  最近在處理 png 圖像解碼時(shí),使用到Uint8Array對(duì)象。發(fā)現(xiàn)該對(duì)象在部分android瀏覽器中沒(méi)有slice方法。翻了一遍API文檔,對(duì)象的slicesubarray方法字面描述基本一樣。于是使用subarray方法取而代之。結(jié)果自然是很悲催了,解析出每幀數(shù)據(jù)都一樣(解碼過(guò)程中有去修改對(duì)象數(shù)據(jù))。

  到這里大概已經(jīng)猜到了subarrayslice的區(qū)別就在于內(nèi)存空間占用上。為探個(gè)究竟,跑個(gè)簡(jiǎn)單的demo來(lái)驗(yàn)證下:

let a = new Uint8Array([1,2,3,4,5,6]);

let b = a.subarray(3,5);
let c = a.slice(3,5);

// 將b的第一個(gè)值改為9
b[0] = 9;

console.log('a',a);
// 輸出:a Uint8Array(6) [1, 2, 3, 9, 5, 6]
console.log('b',b);
// 輸出:b Uint8Array(2) [9, 5]
console.log('c',c);
// 輸出:c Uint8Array(2) [4, 5]

  果然,修改b,a對(duì)應(yīng)的值也是隨之變化的,說(shuō)明是在同一內(nèi)存空間上。而c不與前者內(nèi)存共享,是在獨(dú)立的空間上。

  問(wèn)題是找到了,解決辦法就自然簡(jiǎn)單了。方法有無(wú)數(shù)種。檢查原型是否有對(duì)應(yīng)的方法肯定是必不可少的。如果原型上沒(méi)有slice就自行往原型上添加一個(gè)即可。循環(huán)效率較低,這里還是決定使用原型本身的subarray來(lái)處理。最后解決問(wèn)題的兼容代碼如下:

// 兼容代碼,如果原型上無(wú)`slice`則添加一個(gè)
if(!Uint8Array.prototype.slice){
    Uint8Array.prototype.slice = function(...arg){
        return new Uint8Array(this).subarray(...arg);
    }
};

let a = new Uint8Array([1,2,3,4,5,6]);
let b = b.slice(3,5);

console.log('a',a);
// 輸出:a Uint8Array(6) [1, 2, 3, 4, 5, 6]

console.log('b',b);
// 輸出:b Uint8Array(2) [4, 5]

  這里其實(shí)也比較簡(jiǎn)單,就是新建了一個(gè) Unit8Array 然后去 subarray()。

三、Uint8Array 構(gòu)造函數(shù)對(duì) typedArray 的引用問(wèn)題

  Javascript 的 Uint8Array 支持字節(jié)數(shù)據(jù),對(duì)于操作二進(jìn)制數(shù)據(jù)非常有用,筆者初次接觸時(shí)發(fā)現(xiàn)它有幾個(gè)構(gòu)造函數(shù),如下:

new Uint8Array(); 
new Uint8Array(length);
new Uint8Array(typedArray);
new Uint8Array(object);
new Uint8Array(buffer [, byteOffset [, length]]);

  這些函數(shù)都返回一個(gè) Uint8Array 類型的對(duì)象,但對(duì)于 new Uint8Array(typedArray); 這個(gè)形式的構(gòu)造函數(shù)需要理解一下。在MDN的官方文檔里描述不詳:

   new Uint8Array(typedArray) 表示根據(jù) typedArray 提供的對(duì)象創(chuàng)建一個(gè) Uint8Array 對(duì)象,并保持對(duì)typedArray對(duì)象的引用,這個(gè)形式的構(gòu)造函數(shù)不會(huì)復(fù)制typedArray對(duì)象的。嘗試以下代碼,看看輸出結(jié)果。

// create a TypedArray with a size in bytes
var buffer = new ArrayBuffer(8);
 
var typedArray1 = new Uint8Array(buffer);
typedArray1[0] = 32;
typedArray1[1] = 33;
typedArray1[2] = 34;
 
var typedArray2 = new Uint8Array(buffer);
typedArray2[0] = 42;
typedArray2[1] = 43;
typedArray2[2] = 44;
 
console.log(typedArray1);
//不是輸出 Uint8Array [32, 33, 34, 0, 0, 0, 0, 0]
//正確輸出 Uint8Array [42, 43, 44, 0, 0, 0, 0, 0]
 
console.log(typedArray2);
//正確輸出 Uint8Array [42, 43, 44, 0, 0, 0, 0, 0]
 

  從以上代碼看到了 typedArray1 與 typedArray2 輸出完全一樣。原因就是 typedArray1.buffer 與 typedArray2.buffer 指向的是同一個(gè)對(duì)象,因此分別修改 typedArray1 與 typedArray2 時(shí),實(shí)際上修改的是同一內(nèi)存對(duì)象。

When creating an instance of a TypedArray (e.g. Int8Array), an array buffer is created internally in memory or, if an ArrayBuffer object is given as constructor argument, then this is used instead. The buffer address is saved as an internal property of the instance and all the methods of %TypedArray%.prototype, i.e. set value and get value etc., operate on that array buffer address.

  因此,需要注意的是:用ArrayBuffer 作為構(gòu)造函數(shù)的參數(shù)時(shí),Uint8Array直接引用這個(gè)ArrayBuffer對(duì)象作為內(nèi)部緩沖,而不再創(chuàng)建內(nèi)部ArrayBuffer對(duì)象。

四、Uint8Array 與 String 互轉(zhuǎn)

1、字符串轉(zhuǎn)Uint8Array

function stringToUint8Array(str){
  var arr = [];
  for (var i = 0, j = str.length; i < j; ++i) {
    arr.push(str.charCodeAt(i));
  }
  var tmpUint8Array = new Uint8Array(arr);
  return tmpUint8Array
}

2、Uint8Array轉(zhuǎn)字符串

function Uint8ArrayToString(fileData){
  var dataString = "";
  for (var i = 0; i < fileData.length; i++) {
    dataString += String.fromCharCode(fileData[i]);
  }
  return dataString
}

總結(jié)

以上是生活随笔為你收集整理的浅析Uint8Array语法及常见使用、Uint8Array.slice与Uint8Array.subarray区别(是否指向同一个内存空间)、new Uint8Array(typedArray)构造函数对typedArray的引用问题(保持同一个引用)、Uint8Array与String互相转换的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。