在函数内部的上下文中,这里是代码(基于将函数的'参数'转换为数组的标准模式):
var args = Array.prototype.slice.call(arguments);
我正在尝试研究这个问题(我是JavaScript的初学者,来自C#)。
我理解slice
是一个实例方法,因为它是Array的prototype
函数。
我也明白这不是一个静态的“效用函数”,意味着使用它,你必须new
这样:(例)var myArray = new Array(); myArray.slice(...);
call
传递此处的对象,将上下文更改为arguments
与此相关,我也不知道它们之间的区别
Array.prototype.slice.call([32,32,121,412])
和Array.prototype.slice([32,32,121,412])
不在call
的上下文中。
所以,这是我的问题:
我只是不知道这与实例与静态方法的关系如何...所以任何人都可以解释var args = Array.prototype.slice.call(arguments);
的复杂性吗?
为什么可以在不调用new
的情况下使用它?
为什么这可能?这不是一个静态方法,它必须是'新的',它只能在你使用call
函数... 时起作用(至少在我的C#心态......) < / p>
答案 0 :(得分:1)
Array.prototype.slice.call([32, 32, 121, 412])
和Array.prototype.slice([32, 32, 121, 412])
之间的区别在于,在第一种情况下,实际Array
[32, 32, 121, 412]
成为&#34;此&#34;呼叫的对象。换句话说,它就像这段代码:[32, 32, 121, 412].slice()
。只需在原型上调用slice
就可以在原型对象的上下文中执行它,这可能不会做任何有用的事情。
答案 1 :(得分:1)
将函数添加到对象的原型时,它将成为可以在该对象的实例上使用的函数。该函数的上下文是实例。即。
Array.prototype.myFunction = function() {
alert( this[0] ); // this should refer to the Array instance
};
var x = new Array(1);
x[0] = 5;
x.myFunction(); // alerts 5
但是,有时您可能有一个类似数组的结构,它不是Array的子类或实例(例如Arguments对象)。函数的调用方法的作用是将上下文更改为要调用的第一个参数。在这种情况下,调用方法是在Array的原型函数上调用的。在所有现实中,Array.prototype.myFunction
只是上述代码块中定义的函数。 call
是一种可以在任何函数上调用以更改其上下文的方法。因此,您将拥有一个参数对象,而不是Array实例作为上下文。
function foo() {
Array.prototype.myFunction.call( arguments ); // arguments is [6]
// alerts 6
}
foo( 6 );
答案 2 :(得分:1)
我想也许你会对像Java这样有类的语言中的“实例”和“静态”方法的行为感到困惑。 JavaScript的工作方式不同。
你也对另一个问题感到困惑,那就是所有JS函数调用在被调用函数中设置this
方面的工作方式(即设置函数可能尝试操作的对象)以及效果.call()
设置this
。
.slice()
方法被定义为Array.prototype
的属性,而不是单个数组实例上的Java风格“实例方法”。您可以调用Array.prototype.slice()
,而无需使用new
创建的数组实例。
当你说:
myArray.slice()
JS首先会看到.slice()
实际上是myArray
对象的方法,然后(假设它不是),它会看到它是否是Array原型的方法 - 它是,所以它运行该方法。
当您使用“dot”表示法调用任何JS函数,即myArray.slice()
时,该函数中的特殊变量this
将被设置为该对象。 this
是对函数应该操作的对象的引用。但是如果使用.call()
调用JS函数,则该函数this
将被设置为您作为参数传递给.call()
的对象。所以
myArray.slice()
表示要致电.slice()
并让其在myArray
上运作。
var args = Array.prototype.slice.call(arguments);
表示致电.slice()
并让其在arguments
P.S。不要使用var myArray = new Array();
- 更好地说var myArray = [];
答案 3 :(得分:0)
与C#/ Java不同,函数实际上是JavaScript中的一等公民。
一般意义上说:
这意味着不需要“新”它......它的工作原理完全正确,因为它是它自己的对象。
“新”一个函数(在一般意义上)只是将该函数的“this”值更改为它将被赋值给的变量,然后返回它。
可以在JavaScript中使用一个函数,而无需“新建”它,因为它们是JavaScript中的“一等公民”。
从更深层次的意义上说,这就是“新”所做的事情:
- 它创建一个派生自MyConstructor.prototype的新对象
- 它将构造函数的'this'值赋给新对象
- 在里面执行代码(为新对象/实例添加属性)
- 返回新对象
关于我从实例中学到的内容的一些额外说明:
- 它们没有像构造函数那样的.prototype属性
- 虽然它们有一个[[prototype]]属性,派生自MyConstructor.prototype
- 覆盖实例中的属性会遮蔽MyConstructor.prototype [property] ..