解释都在代码里..<script type="text/javascript">
var join = function () {
for (var i = 0, b = ''; i < this.length ; i ++) {
if (i) b+= arguments[0];
b += this[i];
}
return b;
};var show = function () {
//new Array(arguments)).join('_');
//try
try {
alert(
Array.apply(null, arguments).join('_')
);
return join.call(arguments, '-'); //Array.prototype.join就类似于window.join方法.apply,call不会改变scope,可参考finally里的内容
} finally {
var func = function () {
alert(a);
};
void function () {
var a = 1;
try {
func.call(this);
} catch (exp) {
alert(exp.message);
}
}();
}
};alert(show(1, 2, 3, 5));
var join = function () {
for (var i = 0, b = ''; i < this.length ; i ++) {
if (i) b+= arguments[0];
b += this[i];
}
return b;
};var show = function () {
//new Array(arguments)).join('_');
//try
try {
alert(
Array.apply(null, arguments).join('_')
);
return join.call(arguments, '-'); //Array.prototype.join就类似于window.join方法.apply,call不会改变scope,可参考finally里的内容
} finally {
var func = function () {
alert(a);
};
void function () {
var a = 1;
try {
func.call(this);
} catch (exp) {
alert(exp.message);
}
}();
}
};alert(show(1, 2, 3, 5));
上述代码放到一个空的html里什么结果也没有产生?
楼上的在发表代码之前是否验证过呢?而且,打几个文字就这么困难?也不愿意说明一下。
我看MSDN上很多MS的senior的developer回答问题也并非贴段代码就了事的。
我认为这种问题,用代码来解决最明白了.
apply的原理你已经知道了,所以没有什么好解释的了.
并且我代码里有关键注释.
return join.call(arguments, '-');这句是调用你自己写的join方法变量,也就是window.join方法但这并没有回答我的问题,我不是不知道定义函数变量后调用call方法。
我再强调一下原文的问题:
。那么问题出现了,这个转化又是怎么发生的呢?是系统调用了Array的构造函数吗?
这是确认call和apply的具体实现中是不是调用了构造函数来构造Array对象。
然后下面还有一个问题:
(new Array(arguments)).join('_') 为什么会报错?
new Array(arguments)这部分是可以得到一个Array对象的,但为什么它不能调用join方法呢?
数组的元素中,所以实际上这个得到的Array永远只有一个元素,就是arguments。
即使arguments里有1,2,3,5四个参数,得到的Array也只有一个元素,length=1。这个Array调用join方法,得到的是"[object Object]",
倒是不会报错。而是该arguments对象的toString()得到的结果。但是我的问题仍然没有解决: new Array(arguments)不能“正确”(实际上是按我想的把参数逐一地放到数组里)地得到Array,那么
Array.prototype.join.call(arguments, '_');又是怎么去转化的呢?按muxrwc的代码里Array.Apply(null,arguments)可以把arguments转化成Array对象(而且是逐一地放置元素),是不是调用了它呢?
有什么证据呢?
/*
噢
最近天天困困的而且是从文件中粘贴出那段调试代码。忘记粘那段script了。
既然知道函数后.call
可以调用函数改变this的引用
那么下面这个直接用Array构造创建object对象和.call是一样的道理
*/
alert(Array(1, 2, 3));(function () {
alert(Array(arguments)[0] === arguments); //即[arguments]
alert((new Array(arguments))[0] === arguments); //即[arguments]
//上面两个是等同的
//这个和Function类是一样的.
//你1楼已经说的很清楚了
alert((new Array(arguments)).join('_'));
//这个你也说了[arguments].join自然就是arguments.toString所以是[object...]
//你那里说报错??怎么可能?你不是直接拿着你上面的那个双字节的小左括号测试的吧。。
}(1, 2, 3));
</script>
apply第一个参数
是this的引用地址call函数的2-n参数是
向调用函数传递的1到n-1个参数.而
apply
第二个参数是
一个数组或者arguments对象
把这个组展开放到调用函数的形参中.(展开,是下标相对应的放)
你上面两楼的答案和我上一楼的基本一样。对new方法调用Array的constructor不能构造“展开”的数组已经没有疑问。我的问题现在就是纯粹的对JS这样的弱类型语言里类型转化的实现的一个疑问。
function ClassA()
{
this.p1="pa";
}ClassA.getP1=function()
{
return this.p1;}
function ClassB()
{
ClassA.apply(this,arguments);
this.p1="pb";
}b=new ClassB();
alert( ClassA.getP1.apply(b) );结果还是pb,表面上看很明显,b是ClassB的对象,它的p1当然是pb而不是pa。
但这说明了JS内部有一种机制,不经过构造函数而实现不同类型对象的转化。
可能是受c++的copy constructor的影响,总觉得怎么可能不经过构造函数就可以进行类型转换呢?而且JS严格来说并没有定义ClassA和ClassB的关系。
也就不会有VirtualTable之类的东西。要进行late-binding就比较神奇了啊
所以对Array来说,join方法只需要[]操作符就可以进行,所以可以直接接受arguments对象,即使他不是Array对象,但
他含有[]方法和length属性。如果this是通过方法/属性名就可以寻找到内存中合适的数据。那么确实不需要做类型转换。
直接call/apply就行了。随便乱写,结贴了
new 方法其实是调用Object的构造来实例化array的.
所以typeof 实例化后的array对象,才是object
只不过,最底层的prototype chain是array.prototype chain...偶是这么理解的...
具体的解释方式也不是那么清楚...