Array.prototype.sort.call("foo"); // "[object Object]"
Array.prototype.sort.call(true); // true
Array.prototype.sort.call(1); // 1
Array.prototype.sort.call([1]); // [1]
Array.prototype.sort.call({}); // {}
Array.prototype.sort.call(function() {}); // function() {}
为什么对字符串调用数组方法的行为不同?我认为这是因为String
还有.length
和[]
元素访问者。
任何人都可以解释在错误类型上调用本机方法时究竟发生了什么?
[编辑]
Woops我解决了它。
new Object("foo"); // "[object Object]"
其余部分的行为相同。
让我们谈谈ES5规范:
15.2.1.1 Object([value])当使用no调用Object函数时 参数或一个参数值, 采取以下步骤:
如果value为null,未定义或未提供,则创建并返回一个新值 对象对象完全如同 标准的内置Object构造函数 被称为同样的人 参数(15.2.2.1)。
- 醇>
返回ToObject(值)
ToObject
是:
9.9 ToObject抽象操作ToObject将其参数转换为a Object的值类型 表14:
表14 - ToObject参数 输入结果
未定义扔一个 TypeError异常。
Null扔了一个 TypeError异常。
布尔创建一个 新的Boolean对象 [[PrimitiveValue]]内部属性 设置为参数的值。 有关布尔值的说明,请参见15.6 对象。
号码创建一个新号码 [[PrimitiveValue]]的对象 内部属性设置为 参数的价值。有关a,请参阅15.7 数字对象的描述。
的字符串 创建一个新的String对象 [[PrimitiveValue]]内部属性 设置为参数的值。 有关String的说明,请参见15.5 对象。对象结果是 输入参数(无转换)。
[恩惠]
现在为什么[[PrimitiveValue]]
的{{1}}等于String
?
答案 0 :(得分:1)
回答你的问题
现在为什么String的[[PrimitiveValue]]等于“[object Object]”?
您必须转到ECMAscript standard doc部分15.4.4.11
“让obj成为调用ToObject传递此值作为参数的结果。”
当你Array.prototype.call("abc")
'这个'是字符串“abc”时。将该字符串传递给ToObject与调用new Object("abc")
相同,这是隐式完成的。
此外,值得注意的是Array.prototype.sort.call("foo")
在FF4中生成TypeError。
TypeError:Array.prototype.sort.call(“foo”)是只读的
这是因为需要(也在规范中)如果“ obj的任何数组索引属性,其名称是小于len的非负整数,则定义算法的数据属性 其[[Configurable]]属性为false。“
使用[]访问器无法更改字符串。亲自试试
var test = "abc";
test[1] = 'x';
console.log(test) //'abc'
在遵循规范
时,FF4最有可能更加严格答案 1 :(得分:1)
这里的'问题'是该类型的构造函数被调用(Number, String, Array, Boolean...
),它们的行为与它们的“原始”对应物略有不同 - 它们返回一个包含原始值的对象。
以前规格中的[[PrimitiveValue]]或[[value]]是您可以通过.valueOf()
访问的内部属性。
'foo' // is a string
String('foo') // is a string
new String('foo') // is a String object with [[value]] set to 'foo'
1 // is a number
Number(1) // is a number
new Number(1) // is a Number object with [[value]] set to 1
Object('foo') == (new String('foo'))
Object(1) == (new Number(1))
由于某种原因,webkit检查器似乎并不知道这些对象的原始值。因此,Object('foo')
将打印'[object Object]',但如果您调用Object('foo').toString()
或任何隐式调用toString或valueOf的方法(如alert(Object('foo'))
),则会得到预期值“foo”
这也是原因:
var x = new Boolean(false);
// any object evaluates to true...
!!x // == true
Boolean(x) // == true
Javascript有很多奇怪的东西。还要考虑javascript引擎中有很多怪癖,并且对规范的遵从程度不同。
答案 2 :(得分:1)
[[PrimitiveValue]]
的{{1}} 不 String
,如下所示:
[object Object]
代码中的问题是关键字console.log(String('foo'));
new
console.log(new String('foo'));
关键字将返回new
的实例,其中包含您传递的任何类型构造函数的原型。
答案 3 :(得分:0)
我找到了解决方法。
function callArrayMethod(method, arg1, arg2) {
if (arg2) {
return Array.prototype[method].call(arg1.split(''), arg2).join('');
}
return Array.prototype[method].call(arg1.split(''), arg2).join('');
}
用法:
> callArrayMethod('sort', 'cba');
"abc"