前言

今天仔细阅读了MDN的这篇guide:Using XMLHttpRequest,在里面发现了好多以前听都没听过的概念,尤其是那些不为人知的Object,所以在这里特地把它们拎出来讲一下,不求多深入,只想粗略了解一下。

1、ArrayBuffer

为什么需要这么一种数据类型呢?众所周知,Array对象可以动态变化长度并且可以包含任意类型的JS值。JS引擎对其优化以便可以让这些数组执行起来很快。但是随着web应用变得越来越强大,添加一些诸如音视频的操作特性,使用WebSockets访问原始数据等等和底层有关的行为时,就会发现如果JS能够直接快速且简单地操作原始数据那是相当有用的,于是就产生了ArrayBuffer这样的数据类型。

ArrayBuffer对象用于表示一个通用的固定长度原始二进制数据缓存。你不能直接操作ArrayBuffer的内容。但是你可以使用特定的格式来创建typed array objects或DataView对象以表示这种类型的buffer,然后就可以用来读或者写缓存的内容。那么什么是typed array objectsDataView

1.1、DataView

DataView 视图提供一个底层接口来读取和写入多种数据类型到一个ArrayBuffer中去而忽略平台的大小端。

语法

new DataView(buffer [, byteOffset [, byteLength]])

  1. buffer:一个已存在的ArrayBuffer,用来存储新的DataView对象的;
  2. byteOffset:以字节为单位,新视图存放在相对于指定buffer的第一个字节的偏移。如果没有指定,那么buffer的视图将会从第一个字节开始。
  3. byteLength:字节数组的长度。如果没有指定,视图的长度将会匹配buffer的长度。

该对象提供了众多的方法来读写整形8/16/32比特的有符号整数或者无符号整数以及32/64比特的浮点数,比如:

var buffer = new ArrayBuffer(16); // 创建一个16字节的ArrayBuffer
// 创建一个DataView的对象,放在上面创建的buffer中,偏移为0,
// 也就是在上述buffer中的头部
var dv = new DataView(buffer, 0); // 以小端形式写入一个有符号的16比特的整数到视图中去
dv.setInt16(0, 42, true);
// 以大端形式读取
dv.setInt16(0, 42);
// 以小端形式读取
dv.setInt16(0, 42, true);

大家知道第一个读取的结果和第二个结果是什么吗?答案是:1075242。原因其实很简单的:

42的二进制是:00000000 00101010,如果是小端形式写入buffer的话,那么假设写入到的内存地址是0x10000000(32bit的系统):

内存地址:低-------------------------------------高

0x10000000: 00101010 00000000 00000000 00000000

因为是低字节写在低地址,高字节写在高地址,所以有上面的存储方式。

然后我们以大端的模式读取的时候,是因为低字节写在高地址,高字节写在低地址,所以读取出来的结果便是: 00101010 00000000,所以结果便是10752。

然后小端模式是相反的,所以仍然是42。因为这种差别,所以在MDN上给出了使用这种方式来判断你使用的系统的字节序:

var littleEndian = (function() {var buffer = new ArrayBuffer(2);new DataView(buffer).setInt16(0, 256, true /* littleEndian */);// Int16Array uses the platform's endianness.return new Int16Array(buffer)[0] === 256;
})();
console.log(littleEndian); // true or false

因为Int16Array使用的平台的字节序,所以事先假设为小端模式存储,然后读取出来一对比就知道当前平台使用的字节序了,这种方法值得记住!!

1.2、TypedArray

TypedArray对象描述了一个类数组的底层二进制数据buffer的视图。全局变量中没有TypedArray的属性也没有一个可以直接访问的TypedArray构造体。不过全局变量中有一组不同的属性,它们的值是有指定元素类型的typed array结构体,

ES6定义了一个TypedArray构造体作为所有TypedArray构造体的[[Prototype]]。这个构造体并没有直接暴露出去:也就是说没有全局变量%TypedArray%或者TypedArray属性。它只能通过Object.getPrototypeOf(Int8Array)或者类似的属性(Int8Array可以改为下面列举的任意一个函数)直接访问。所有的TypedArray构造体从%TypedArray%构造体函数继承了公共的属性。另外所有的typed array原型(TypedArray.prototype)都将%TypedArray%.prototype作为它们的[[Prototype]]。

比如:

var dv = new Int8Array(4)

dv的结构可以在控制台上看到:

%TypedArray%构造体并不是特别有用,调用它或者在一个新的表达式中使用它将会抛出一个TypeError的错误,除了当你在支持子类的JS引擎中对象的创建。目前没有这样的引擎,所以%TypedArray%只对polyfill函数或者所有TypedArray构造体上的属性有用。

当创建一个TypedArray实例(也就是Int8Array或者类似函数的实例),将在内存中创建一个数组缓存(如果ArrayBuffer对象作为构造体参数那么就使用这个array buffer),该缓存的地址作为该实例的内部属性保存起来,并且%TypedArray%.prototype的所有方法使用该缓存地址进行各种操作。

全部的具体对象如下所示:

new TypedArray(length);
new TypedArray(typedArray);
new TypedArray(object);
new TypedArray(buffer [, byteOffset [, length]]);where TypedArray() is one of:Int8Array();
Uint8Array();
Uint8ClampedArray();
Int16Array();
Uint16Array();
Int32Array();
Uint32Array();
Float32Array();
Float64Array();

上面新建的对象都可以使用标准的数组索引语法去访问数组的每个元素。但是在typed arrays上获取或设置索引的属性是不会去搜索该属性上的原型链的,即使当索引已经溢出。索引的属性将会从ArrayBuffer中查找而不会去查找对象的属性。你仍然可以使用命名的属性。

比如:

Int8Array.prototype.foo = "bar";
var dv = new Int8Array(4);

那么现在新建的任何Int8Array的原型都将会有这个一个foo的属性:

具体的范例参考MDN上提供的:TypedArray

1.3、实例操作

基本上ArrayBuffer用于存储二进制数据,比如一张图片,然后你就可以在这张图片的基础上做各种操作比如添加alpha做成有RBGA形式的新图片。在MDN的JavaScript typed arrays中大体解释了其适用的几个场景。

更多实用的例子可以参考:Sending and Receiving Binary Data

2、Blob对象

一个Blob对象代表的是一种类似于文件的不可变的原始数据,也即是说blob对象表示一堆用来呈现文件数据字节,但它并不能索引到真正的文件。Blobs表示的数据在原生的JS格式中是不必要的。blob对象和文件一样有自己的长度以及MIME类型。Js的File接口就是基于Blob,它继承了Blob的所有功能并扩展以能够支持用户系统中的文件。

Blob的大部分API都是异步的,但是也有同步的API可用所以它们可以在Web Workers中使用。

blob对象的内容可以作为ArrayBuffer来读取。

比如,先创建一个blob对象:

var myBlob = new Blob(["This is my testing of blob"], {type : "text/plain"});

然后我们使用FileReader来读取内容:

var myReader = new FileReader();
myReader.addEventListener("loadend", function(e){console.log(e.srcElement.result);//prints a string
});
//start the reading process.
myReader.readAsText(myBlob);

Blob对象的数据也可以通过使用URL的形式(blob:// URLs)获取,这个时候使用createObjectURL来获取,比如:

//cross browserwindow.URL = window.URL || window.webkitURL;var blob = new Blob(['body { background-color: yellow; }'], {type: 'text/css'});var link = document.createElement('link');
link.rel = 'stylesheet';
//createObjectURL returns a blob URL as a string.
link.href = window.URL.createObjectURL(blob);
document.body.appendChild(link);

除此之外还可以使用AJAX将得到的一些二进制流存储起来:

var xhr = new XMLHttpRequest();
xhr.open("GET", "/favicon.png");
xhr.responseType = "blob";//force the HTTP response, response-type header to be blob
xhr.onload = function()
{document.getElementsByTagName("body")[0].innerHTML = xhr.response;//xhr.response is now a blob object
}
xhr.send();

接着我们可以在ArrayBuffer中获取blob内容然后分析,这个过程可以调用FileReader.readAsArrayBuffer()来完成。

var xhr = new XMLHttpRequest();
xhr.open("GET", "/favicon.png");
//although we can get the remote data directly into an arraybuffer using the string "arraybuffer" assigned to responseType property. For the sake of example we are putting it into a blob and then copying the blob data into an arraybuffer.
xhr.responseType = "blob";function analyze_data(blob)
{var myReader = new FileReader();myReader.readAsArrayBuffer(blob)myReader.addEventListener("loadend", function(e){var buffer = e.srcElement.result;//arraybuffer object});
}xhr.onload = function()
{analyze_data(xhr.response);
}
xhr.send();

3、File对象

一个File对象指的是本地文件系统中的一个实际的文件。在上面我们说过File对象继承了Blob类的所有属性和方法。所以说虽然二者是不同的,但是却暴露了相同的方法和属性。

没有特定的方法去创建一个File对象,但是一些JS的API会返回对File对象的引用。File对象可以从一组用户选择的文件列表中返回的FileList对象获取也可以从一个拖拽操作的 DataTransfer对象中获取:

var element = document.getElementsByTagName("body")[0];//files is a filelist
function fileselected(files)
{for(var i = 0; i < files.length; i++) {var f = files[i];element.innerHTML = element.innerHTML + f.name + " " + f.size + " " + f.type; }
}

4、Plain对象

这个概念不是JS原生的,而是Jquery提供的。根据Jquery的官方文档解释:

PlainObject类型是一种包含零个或者多个键值对的对象。这种纯粹的对象换句话说是一个`Object`对象。它在Jquery中被设计成“纯粹”是为了和JS其他的内建对象做区别:比如`null`,用户定义的数组,以及主机内建的对象`document`等等。

PlainObject的创建应该是使用{}或者new Object.

注意: Host对象(或浏览器宿主环境中所使用的对象,用来完成的ECMAScript执行环境)在检测跨平台时存在很多的不一致,难以提供跨平台的强劲的检测函数。在某些情况下,$.isPlainObject()的结果可能在不同的浏览器评估不一致。

参考:

  1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView
  2. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray
  3. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
  4. //api.jquery.com/jquery.isplainobject/
  5. https://api.jquery.com/Types/

javascript中打印对象显示[object object]_扒一扒JavaScript中不常见的一些object相关推荐

  1. javascript中打印对象显示[object object]_js如何打印object对象

    这篇文章主要介绍了js如何打印object对象,需要的朋友可以参考下 js调试中经常会碰到输出的内容是对象而无法打印的时候,光靠alert只能打印出object标示,却不能打印出来里面的内容,甚是不方 ...

  2. 深入分析Java中打印对象内存地址 System.identityHashCode()方法

    文章目录 地址是什么样子的 toString()方法 重写hashCode identityHashCode与真正的内存地址 参考 地址是什么样子的 我们知道system.out.println(ne ...

  3. java 打印对象属性 工具类_关于java实现任意对象输出字符串的工具类ObjectUtils用户打印日志、接口调试及监控等...

    通过该对象工具类ObjectUtils(参考org.springframework.util.ObjectUtils)实现了类集.数组及基本数据类型转换及字符串输出,常用在日志输出打印.接口联调及对象 ...

  4. 无侵入性的在日志中打印对象的关键字段

    我们在开发的时候,经常要打印日志,有的时候会在一些代码的关键节点处进行日志输出. 使用logback/log4j等原生的日志框架,在日志输出的时候可能会遇到一个问题,那就是在打印对象的时候要求对象必须 ...

  5. wincc显示系统时间_在WINCC画面组态中,如何显示系统时间?-工业支持中心-西门子中国...

    在wincc 的智能对象中 使用控件 选择DaclockCtrl 即可 调用的控件名称为WINCC Digital/Analog clock ctrol 回答者: KCN - 顶级工程师&nb ...

  6. java对象流读取完毕_从Java 8流中获取具有最大频率的对象

    我有一个带有city和zip字段的对象,我们称之为Record. public class Record() { private String zip; private String city; // ...

  7. java中的图形界面编辑界面_第58节:Java中的图形界面编程-GUI

    欢迎到我的简书查看我的文集 前言: GUI是图形用户界面,在Java中,图形用户界面我们用GUI表示,而GUI的完整英文为: Graphical User Interface(图形用户接口), 所谓图 ...

  8. qt中如何模拟按钮点击_如何快速在 Shopify 中加入按钮

    假如你会 `CSS` , `HTML` , `JS` 三件套,那么修改 `Shopify` 代码将不会太难(毕竟一个模板中的代码量还是挺多的,除非深入研究了代码,不然改起来还是会比较麻烦的). 但挺多 ...

  9. mysql中为表增加外键_如何在Excel 2013中为符号分配键盘快捷键

    mysql中为表增加外键 We've previously shown you how to add keyboard shortcuts to symbols in Word 2013 to mak ...

最新文章

  1. DL之HNN:基于HNN(subplot)将凌乱数字矩阵图像(模拟手写数字图片)实现转为最相近的阿拉伯数字
  2. kylin如何支持flink_大数据集群运维(28) Kylin 配置使用 flink 构建 Cube
  3. HDU 4912 Paths on the tree(LCA+贪心)
  4. oracle 网关下载,oracle透明网关访问sqlserver2000
  5. 写java代码时的注意事项_从方法返回Java 8的可选项时的注意事项
  6. 带有Hibernate OGM的NoSQL –第二部分:查询数据
  7. android app源码大全_Android秋招秘籍,看我如何搞定BAT,Vivo,爱奇艺
  8. 系统总线频率和外频有何区别?
  9. 【转】Android之apk文件签名——keytool 和 jarsigner
  10. Android 笔记
  11. 优雅的对 list 遍历进行 add 或者 remove 操作
  12. 五笔字根表识别码图_王码86版五笔字根表口诀助记词(完整大图)
  13. 【c语言】打印出100以内奇数
  14. 【堆排序的递归和非递归实现】Java实现
  15. 《老路用得上的商学课》96-100学习笔记
  16. 用SPSS-Modeler分析银行信用风险评分方法
  17. 前端 报培训班还是自学
  18. unity 3d水的资源包_使用Apple LiDAR,一小时为你家量身打造3D游戏
  19. ArcGIS Online试用版注册 并发布要素服务
  20. 精简JavaScript

热门文章

  1. cas3 自定义页面
  2. mysql replace
  3. Golang map 三板斧第一式:快速上手
  4. 快速读取内存文件-内存映射文件的方法
  5. ubuntu16.04 内核源码编译
  6. POJ 3159 Candies 差分约束dij
  7. android 简易时间轴(实质是ListView)
  8. pl sql练习(3)
  9. v-for列表渲染之数组变动检测
  10. HQL 如何 count(*) 分页查询出来 group by 的总数?