我不应该像这样向数组中添加元素:
var b = [];
b.val_1 = "a";
b.val_2 = "b";
b.val_3 = "c";
我不能使用本机数组方法,为什么不只是一个对象。我只是在数组中添加属性,而不是元素。我想这使它们与length
属性并行。虽然尝试重置长度(b.length = "a string"
)会获得Uncaught RangeError: Invalid array length
。
无论如何,我仍然可以看到我设置的属性:
console.log(b); //[val_1: "a", val_2: "b", val_3: "c"]
我可以使用点语法访问它:
console.log(b.val_1); //a
如果一个数组只是一个对象,字符串或数字就是一个对象,为什么不能(不是我想要的)我用这种语法为它们附加属性:
var num = 1;
num.prop_1 = "a string";
console.log(num); //1
我无法使用点语法
访问其属性console.log(num.prp); //undefined
为什么可以使用数组而不是其他数据类型。对于所有情况,我应该使用{}
并且只需要使用{}
,那么为什么数组有这种能力呢?
答案 0 :(得分:7)
由于数组被语言视为对象,因此您可以通过键入以下代码行来查看:
console.log(typeof []) // object
但是其他类型,如数字文字,字符串文字NaN
...等都是原始类型,并且只包含在由语言定义的某些上下文中的对象代理中。
如果要向这样的数字添加属性或方法,那么可以像这样使用Number
构造函数:
var num = new Number(1);
num.prop_1 = "fdadsf";
console.log(num.prop_1);
使用Number
构造函数返回一个数字对象,您可以通过键入以下行来查看该对象:
console.log(typeof num); // object
在第一种情况下:
var num = 1;
console.log(typeof num) // number
编辑2:例如,当您在数字文字或字符串文字上调用方法时,该原语会被方法调用的语言自动包装到其对象表示中,例如:
var num = 3;
console.log(num.toFixed(3)); // 3.000
这里num
是一个原始变量,但是当你在它上面调用toFixed()
metohd时,它会被包装到Number
对象,因此可以进行方法调用。
编辑:在第一种情况下,您首先创建了一个类似于此字符串var str = new String()
的字符串,然后将其更改为str = "asdf"
,然后分配了属性{{1} }。
当然,这不起作用,因为当您分配str.var_1 = "1234"
时,str = "asdf"
成为基本类型,而最初创建的Object实例现在已经消失,您无法添加属性原始人。
在第二个中,它没有像你说的那样输出str
,我在undefined
测试了它,一切正常。
编辑3:
字符串文字(用双引号或单引号表示)和非构造函数上下文中String调用返回的字符串(即不使用new关键字)是原始字符串。
这取自MDN Documentation,当您使用类似Firebug
的字符串时,它变为转换函数而不是构造函数,并且它返回原始字符串,如上面的引用所示。
关于您的第二条评论,我不明白我的评论是如何被藐视的,因为如果您尝试var p = String(3)
,您将获得console.log(p.pr)
,证明undefined
是原始类型而不是一个对象。
答案 1 :(得分:2)
如果一个数组只是一个对象,那么字符串或数字就是一个对象,
数组不同于字符串,数字,布尔值,null和undefined。数组是一个对象,而列表中的其他数组是原始值。您可以像对待任何其他对象一样向数组添加属性,任何不同的东西都是使数组特殊的原因(例如,您提到的长度属性)。您无法在原始值上添加属性或调用方法。
在this之前的回答中,我谈到了对原始值使用Object包装器。随意阅读它以查看有关Object包装器的更多信息。以下是一个非常简短的例子:
console.log('TEST'.toLowerCase()) // 'test'
虽然看起来在字符串'TEST'上调用toLowerCase方法,但实际上字符串会自动转换为String对象,并且在String对象上调用toLowerCase方法。
每次调用字符串,数字或布尔值的属性时,都会创建一个适当类型的新Object包装器来获取或设置该值(设置属性可能完全被浏览器优化掉,我不确定这一点)。
根据你的例子:
var num = 1; // primitive value
num.prop_1 = "a string"; // num is converted to a Number, the prop_1 property is set on the Object which is discarded immediately afterwards
console.log(num); //1 // primitive value
console.log(num.prp); // num is converted to a Number, which doesn't have the prp property
我的例子:
Number.prototype.myProp = "works!";
String.prototype.myFunc = function() { return 'Test ' + this.valueOf() };
Boolean.prototype.myTest = "Done";
console.log(true.myTest); // 'Done'
console.log('really works!'.myFunc()); // 'Test really works!'
var x = 3;
console.log(x.myProp.myFunc()); // 'Test works!'
console.log(3['myProp']); // 'works!'
另一方面:
console.log(3.myProp); // SyntaxError: Unexpected token ILLEGAL
这个数字不一定区别对待,语法只会混淆解析器。以下示例应该有效:
console.log(3.0.myProp); // 'works!'