繁体   English   中英

类数组对象是数据类型吗

[英]Is array-like object a datatype

正如我发现,如果类数组对象(即arguments数组)是JavaScript数据类型还是不是JavaScript数据类型,我在徘徊的材料中存在一些不一致之处? 通常,我们谈论数据类型的原因如下:字符串,数字,布尔值,数组,对象,空值,未定义。 但是我想像数组一样的对象也是预定义的,所以我不知道为什么不包括它们。

“类数组对象”是具有数字索引和length属性(指示其包含多少个值)的任何对象。

“类似数组的对象”不是数据类型,而只是适合该描述的某些对象的类别。 例如,以下是一个类似数组的对象,它直接从Object派生,而不是更具体的Object

var alo = {
    0: "hello",
    1: 3,
    length: 2
};

您通常可以在类似数组的对象上使用某些数组操作,它们仍然像数组一样工作。 特别是,您可以使用slice()方法将类似数组的对象转换为实际数组:

var a = Array.prototype.slice.call(alo); // a is an actual array with the values
                                         // "hello" and 3

您可以直接在类似数组的对象上使用某些数组方法,而无需先将它们转换为数组。 以下显示“ hello”和“ 3”:

Array.prototype.forEach.call(alo,function(v){console.log(v);})

不,类似数组的对象之所以这样称呼,是因为它们只是一个带有整数键的对象。 例:

var myArraylike = {
    0: "someValue",
    1: "moreValues",
    "length": 2
};
myArraylike[0] == "someValue"; //true

正如您可以通过运行以下命令注意到的那样,它们不被视为其自身的数据类型:

typeof myArraylike; //returns "object"

请注意,由于原型概念的原因,其他“对象”本身并不是自己的数据类型:

typeof Array; //returns "function"

构造函数只不过是函数,它们的乘积是一个对象:

typeof new Array(); //returns "object"

但是这些对象( ArrayDate等的实例)如何被视为自己的类型? 答案是上述“原型”概念。 让我们定义我们自己的“类型”!

function CoolType() {
    this.y = 10;
}
CoolType.prototype.doCoolStuff = function() {
    console.log(this.y);
}

我们创建了一个引用this的函数,这是一个可解析为当前对象的特殊关键字。 我们还在CoolType的特殊prototype属性中定义了一个名为doCoolStuff的函数。

当我们实例化CoolType (使用new )时,其原型被复制到新创建的对象中,然后执行CoolType函数体:

var x = new CoolType();
x.doCoolStuff(); //prints 10

对象上不存在的任何属性都将从其原型中检索(反过来,如果它也没有此类属性,则将检查其原型)。 这样,您可以从对象继承行为:

function AwesomeType() {
    this.y = 42;
}

AwesomeType.prototype = CoolType;

var x = new AwesomeType();
x.doCoolStuff(); //prints 42

您可能会想:“所有这些与类数组对象有什么关系??”,原因是:类数组对象是行为类似于数组的对象(具有长度和数字键属性,如上所示) ,但其原型不是Array

javascript类型系统有些不一致。 存在哪种类型取决于您的要求。 获取值类型的最基本方法是使用typeof运算符:

typeof(2) // 'number'
typeof('foo') // 'string'
typeof(true) // 'boolean'
typeof(undefined) // 'undefined'
typeof(null) // 'object'
typeof([]) // 'object'
typeof({}) // 'object'
typeof((function(){return arguments;})()) // 'object'

如您所见, typeof运算符将arguments视为对象,但随后又将普通数组视为对象,因此为null。 (出于琐碎的兴趣,null实际上是一个对象,原因是该语言的原始实现的早期错误已被锁定在规范中)。 还有其他方法可以判断值的类型。 一种常见的技术是使用Object.prototype.toString.call()

Object.prototype.toString.call(2) // '[object Number]'
Object.prototype.toString.call('foo') // '[object String]'
Object.prototype.toString.call(true) // '[object Boolean]'
Object.prototype.toString.call(undefined) // '[object Undefined]'
Object.prototype.toString.call(null) // '[object Null]'
Object.prototype.toString.call([]) // '[object Array]'
Object.prototype.toString.call({}) // '[object Object]'
Object.prototype.toString.call((function(){return arguments;})()) // '[object Arguments]'

如您所见,此方法更为有效。 它确实有局限性。 具体由用户定义的类:

Object.prototype.toString.call(new (function Foo(){})()) // '[object Object]'

查找对象类名称的最佳方法是.constructor

(2).constructor.name // 'Number'
('foo').constructor.name // 'String'
(true).constructor.name // 'Boolean'
(undefined).constructor.name // TypeError
(null).constructor.name // TypeError
([]).constructor.name // 'Array'
({}).constructor.name // 'Object'
((function(){return arguments;})()).constructor.name // 'Object'
(new (function Foo(){})()).constructor.name // 'Foo'

如您所见,这不适用于参数,null或undefined。 这可能是该镀铬控制台使用兴趣constructor.name当它显示与用户定义的类值:

// (Chrome only)

>   ({a: 1})
<-  Object {a: 1}

>   new (function Foo(){this.a = 1;})()
<-  Foo {a: 1}

>   ({constructor: {name: 'Bar'}})
<-  Bar {constructor: Object}

在实践中,我倾向于使用下划线中定义的类型方法进行大多数类型检查。

参数在许多实际方面也与数组不同。 具体来说,虽然数组的length属性在被修改时会更新,但参数不会被更新,但是数组中内置的方法也不会在参数上内置:

[1,2,3,4,5].slice(2,4) // [3, 4]
x = (function(){return arguments})(1,2,3,4,5)
x.slice(2, 4) // TypeError

但是有一种解决方法:

[].slice.call(x, 2, 4) // [3, 4] 

(以上内容已在Node.js,Chrome和Firefox中进行了测试)(互联网浏览器明显与此不同)

数组是用于存储数据类型和其他对象的对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM