Javascript Array.prototype.slice.call()如何工作?
我知道它被用来使参数成为一个真正的数组,但我不明白当使用Javascript Array.prototype.slice.call()如何工作?,javascript,prototype-programming,Javascript,Prototype Programming,我知道它被用来使参数成为一个真正的数组,但我不明白当使用array.prototype.slice.call(arguments)时会发生什么,它使用数组拥有的slice方法,并使用this作为参数对象来调用它。这意味着它调用它时,就好像您执行了arguments.slice()假设arguments有这样一个方法一样 创建一个没有任何参数的切片只需获取所有元素,因此它只需将元素从参数复制到一个数组中。通常,调用 var b = a.slice(); function hasArrayNatu
array.prototype.slice.call(arguments)
时会发生什么,它使用数组拥有的slice
方法,并使用this
作为参数对象来调用它。这意味着它调用它时,就好像您执行了arguments.slice()
假设arguments
有这样一个方法一样
创建一个没有任何参数的切片只需获取所有元素,因此它只需将元素从参数
复制到一个数组中。通常,调用
var b = a.slice();
function hasArrayNature(a) {
return !!a && (typeof a == "object" || typeof a == "function") && "length" in a && !("setInterval" in a) && (Object.prototype.toString.call(a) === "[object Array]" || "callee" in a || "item" in a);
}
function $A(b) {
if (!hasArrayNature(b)) return [ b ];
if (b.item) {
var a = b.length, c = new Array(a);
while (a--) c[a] = b[a];
return c;
}
return Array.prototype.slice.call(b);
}
将数组a
复制到b
。然而,我们不能这样做
var a = arguments.slice();
因为参数
不是真正的数组,并且没有切片
作为方法Array.prototype.slice
是数组的slice
函数,调用call
运行函数时将此设置为参数让我们假设您有:函数。应用(thisArg,argArray)
apply方法调用一个函数,传入将绑定到此函数的对象
和一个可选的参数数组
slice()方法选择数组的一部分,并返回新数组
因此,当您调用Array.prototype.slice.apply(arguments,[0])
时,将对参数调用数组切片方法(bind)。这是因为
arguments对象不是数组。它类似于数组,但是
除了长度之外,没有任何数组属性。例如,它确实如此
没有流行的方法。但是,它可以转换为实际阵列:
这里我们调用的是本机对象数组上的slice
,而不是它的实现,这就是为什么额外的.prototype
var args = Array.prototype.slice.call(arguments);
arguments
对象实际上不是数组的实例,并且没有任何数组方法。因此,arguments.slice(…)
将不起作用,因为arguments对象没有slice方法
数组确实有这个方法,因为参数
对象与数组非常相似,所以两者是兼容的。这意味着我们可以对arguments对象使用数组方法。由于数组方法是在考虑数组的情况下构建的,因此它们将返回数组而不是其他参数对象
那么为什么要使用Array.prototype
?Array
是我们从中创建新数组的对象(newarray()
),这些新数组是传递的方法和属性,如slice。这些方法存储在[Class].prototype
对象中。因此,为了提高效率,我们不是通过(new Array()).slice.call()
或[].slice.call()
访问slice方法,而是直接从原型获得它。这样我们就不必初始化新数组
但我们为什么要这么做呢?正如您所说,它将arguments对象转换为数组实例。然而,我们使用slice的原因更多的是一种“黑客”行为。slice方法将获取数组的一个切片,并将该切片作为新数组返回。不向其传递任何参数(除了作为其上下文的arguments对象之外)会导致slice方法获取传递的“数组”(在本例中为arguments对象)的完整块,并将其作为新数组返回。在后台发生的事情是,当正常调用.slice()
时,这是一个数组,然后它就在这个数组上迭代,完成它的工作
//ARGUMENTS
function func(){
console.log(arguments);//[1, 2, 3, 4]
//var arrArguments = arguments.slice();//Uncaught TypeError: undefined is not a function
var arrArguments = [].slice.call(arguments);//cp array with explicity THIS
arrArguments.push('new');
console.log(arrArguments)
}
func(1,2,3,4)//[1, 2, 3, 4, "new"]
这个在.slice()
函数中是如何作为数组的?因为当你这样做的时候:
object.method();
…在方法()中,对象
自动成为此
的值。因此:
[1,2,3].slice()
…将[1,2,3]
数组设置为.slice()
中的this
的值
但是,如果您可以将其他内容替换为this
值,该怎么办?只要替换的内容有一个数值.length
属性和一组数值索引属性,它就应该可以工作。这种类型的对象通常称为类似数组的对象
.call()
和.apply()
方法允许您在函数中手动设置this
的值。因此,如果我们在.slice()
中将this
的值设置为类似于数组的对象,.slice()
将假定它正在处理数组,并将执行它的操作
以这个普通对象为例
var my_object = {
'0': 'zero',
'1': 'one',
'2': 'two',
'3': 'three',
'4': 'four',
length: 5
};
这显然不是一个数组,但是如果您可以将它设置为.slice()
的This
值,那么它就可以正常工作,因为它看起来足够像一个数组,可以让.slice()
正常工作
var sliced = Array.prototype.slice.call( my_object, 3 );
示例:
正如您在控制台中看到的,结果是我们所期望的:
['three','four'];
因此,当您将arguments
对象设置为.slice()
的this
值时,就会发生这种情况。因为arguments
有一个.length
属性和一组数字索引,.slice()
就像在一个真实的数组上工作一样工作。不要忘记,这种行为的底层基础是完全集成在JS引擎中的类型转换
Slice只接受对象(由于存在arguments.length属性),并返回在对该对象执行所有操作后铸造的数组对象
如果尝试使用INT值处理String方法,则可以测试相同的逻辑:
String.prototype.bold.call(11); // returns "<b>11</b>"
String.prototype.bold.call(11);//返回“11”
这就解释了上面的说法。我写这篇文章只是为了提醒自己
Array.prototype.slice.call(arguments);
== Array.prototype.slice(arguments[1], arguments[2], arguments[3], ...)
== [ arguments[1], arguments[2], arguments[3], ... ]
或者只需使用这个方便的函数$A就可以将大多数内容转换为一个数组
function hasArrayNature(a) {
return !!a && (typeof a == "object" || typeof a == "function") && "length" in a && !("setInterval" in a) && (Object.prototype.toString.call(a) === "[object Array]" || "callee" in a || "item" in a);
}
function $A(b) {
if (!hasArrayNature(b)) return [ b ];
if (b.item) {
var a = b.length, c = new Array(a);
while (a--) c[a] = b[a];
return c;
}
return Array.prototype.slice.call(b);
}
示例用法
function test() {
$A( arguments ).forEach( function(arg) {
console.log("Argument: " + arg);
});
}
正常调用.slice()时,这是一个数组,然后它只在该数组上迭代,并执行其工作
//ARGUMENTS
function func(){
console.log(arguments);//[1, 2, 3, 4]
//var arrArguments = arguments.slice();//Uncaught TypeError: undefined is not a function
var arrArguments = [].slice.call(arguments);//cp array with explicity THIS
arrArguments.push('new');
console.log(arrArguments)
}
func(1,2,3,4)//[1, 2, 3, 4, "new"]
var slice = Array.prototype.slice;
slice.call(someObject, 1, 2);
Array.prototype.slice.call(someObject, 1, 2);
function Teacher(first, last, age, gender, interests, subject) {
Person.call(this, first, last, age, gender, interests);
this.subject = subject;
}
let args = Array.from(arguments);
let args = [...arguments];
/*
arguments: get all args data include Length .
slice : clone Array
call: Convert Object which include Length to Array
Array.prototype.slice.call(arguments):
1. Convert arguments to Array
2. Clone Array arguments
*/
//normal
function abc1(a,b,c){
console.log(a);
}
//argument
function: function abc2(){
console.log(Array.prototype.slice.call(arguments,0,1))
}
abc1('a','b','c');
//a
abc2('a','b','c');
//a