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