[javascript] Array.prototype.slice.call ()은 어떻게 작동합니까?

나는 그것이 인수를 실제 배열로 만드는 데 사용된다는 것을 알고 있지만 사용할 때 어떤 일이 발생하는지 이해하지 못한다 Array.prototype.slice.call(arguments)



답변

후드 아래에서 발생하는 .slice()것은 정상적으로 호출 될 때 this배열이며 배열을 반복하고 작업을 수행한다는 것입니다.

함수 this에서 어떻게 .slice()배열입니까? 당신이 할 때 :

object.method();

…는 object자동의 값이된다 this하여 method(). 따라서 :

[1,2,3].slice()

[1,2,3]배열은 thisin 의 값으로 설정됩니다 .slice().


그러나 다른 것을 this가치 로 대체 할 수 있다면 어떨까요? 대체하는 것이 숫자 .length속성과 숫자 인덱스 인 많은 속성을 갖는 한 작동합니다. 이 유형의 객체를 종종 배열 형 객체 라고 합니다 .

.call().apply()방법은 당신이 할 수 수동으로 값을 설정 this하는 기능에. 우리의 값으로 설정 그래서 경우 this에를 .slice()배열과 같은 객체 , .slice()단지 것입니다 가정 이 배열로 일하고, 그 일을 할 것입니다.

이 평범한 물체를 예로 들어 보겠습니다.

var my_object = {
    '0': 'zero',
    '1': 'one',
    '2': 'two',
    '3': 'three',
    '4': 'four',
    length: 5
};

이것은 분명히 배열이 아니지만 this값을 로 설정할 수 있으면 제대로 작동 .slice()하기 .slice()에 충분히 배열처럼 보이기 때문에 작동합니다.

var sliced = Array.prototype.slice.call( my_object, 3 );

예 : http://jsfiddle.net/wSvkv/

콘솔에서 볼 수 있듯이 결과는 다음과 같습니다.

['three','four'];

따라서 arguments객체를 this값으로 설정하면 이런 일이 발생합니다 .slice(). 속성과 많은 숫자 인덱스 arguments가 있기 때문에 실제 배열에서 작업하는 것처럼 작업을 수행합니다..length.slice()


답변

arguments객체는 실제로 배열의 인스턴스가 아닌, 및 배열 방법을 가지고 있지 않습니다. 따라서 arguments.slice(...)arguments 객체에 slice 메서드가 없으므로 작동하지 않습니다.

배열에는이 방법이 있으며 arguments객체는 배열과 매우 유사하기 때문에 두 개가 호환됩니다. 즉, arguments 객체와 함께 배열 메서드를 사용할 수 있습니다. 그리고 배열 메소드는 배열을 염두에두고 작성되었으므로 다른 인수 오브젝트가 아닌 배열을 리턴합니다.

왜 사용 Array.prototype합니까? 는 Array우리가 (의 새로운 배열을 생성하는 객체입니다 new Array()), 그리고이 새로운 배열은 조각처럼, 방법 및 속성을 전달됩니다. 이러한 메소드는 [Class].prototype객체에 저장됩니다 . 따라서 효율성 향상을 위해 (new Array()).slice.call()또는로 슬라이스 방법에 액세스하는 대신 [].slice.call()프로토 타입에서 바로 가져옵니다. 따라서 새로운 배열을 초기화 할 필요가 없습니다.

그러나 왜 우리는 처음에 이것을해야합니까? 글쎄, 당신이 말했듯이, 그것은 arguments 객체를 Array 인스턴스로 변환합니다. 그러나 슬라이스를 사용하는 이유는 무엇보다 “핵”입니다. slice 메소드는 배열의 슬라이스를 가져 와서 그 슬라이스를 새로운 배열로 반환합니다. arguments 객체를 인수로 컨텍스트에 전달하지 않고 전달하면 slice 메서드는 전달 된 “배열”(이 경우 arguments 객체)의 전체 청크를 가져 와서 새 배열로 반환합니다.


답변

일반적으로 전화

var b = a.slice();

배열 a을에 복사합니다 b. 그러나 우리는 할 수 없습니다

var a = arguments.slice();

arguments실제 배열이 아니며 slice메소드 가 없기 때문 입니다 . Array.prototype.slice는 IS slice배열 기능과 call함께 기능을 실행 this에 집합 arguments.


답변

먼저 JavaScript에서 함수 호출이 작동하는 방식 을 읽어야 합니다 . 혼자서도 귀하의 질문에 대답하기에 충분하다고 생각합니다. 그러나 여기에 무슨 일이 일어나고 있는지 요약되어 있습니다.

Array.prototype.slice추출물 방법 에서 의 프로토 타입 . 그러나 메서드 (함수가 아님) 이므로 컨텍스트 (호출 객체 ) 가 필요하므로 직접 호출하면 작동 하지 않습니다 . 그렇지 않으면 throw 됩니다.slice ArraythisUncaught TypeError: Array.prototype.slice called on null or undefined

call()메소드를 사용하면 메소드의 컨텍스트를 지정할 수 있으며 기본적으로이 두 호출을 동일하게 만듭니다.

someObject.slice(1, 2);
slice.call(someObject, 1, 2);

전자의 경우를 제외하고는 slice메소드가 someObject프로토 타입 체인 에 있어야 Array하지만, 후자는 컨텍스트 ( someObject)를 메소드에 수동으로 전달할 수 있습니다.

또한 후자는 다음과 같이 짧습니다.

var slice = Array.prototype.slice;
slice.call(someObject, 1, 2);

다음과 같습니다.

Array.prototype.slice.call(someObject, 1, 2);


답변

// We can apply `slice` from  `Array.prototype`:
Array.prototype.slice.call([]); //-> []

// Since `slice` is available on an array's prototype chain,
'slice' in []; //-> true
[].slice === Array.prototype.slice; //-> true

// … we can just invoke it directly:
[].slice(); //-> []

// `arguments` has no `slice` method
'slice' in arguments; //-> false

// … but we can apply it the same way:
Array.prototype.slice.call(arguments); //-> […]

// In fact, though `slice` belongs to `Array.prototype`,
// it can operate on any array-like object:
Array.prototype.slice.call({0: 1, length: 1}); //-> [1]


답변

Array.prototype.slice.call (arguments)는 인수를 배열로 변환하는 구식 방법입니다.

ECMAScript 2015에서는 Array.from 또는 스프레드 연산자를 사용할 수 있습니다.

let args = Array.from(arguments);

let args = [...arguments];


답변

그 때문에, 같은 MDN 노트

arguments 객체는 배열이 아닙니다. 배열과 비슷하지만 길이를 제외하고 배열 속성이 없습니다. 예를 들어, pop 메소드가 없습니다. 그러나 실제 배열로 변환 할 수 있습니다.

여기에서 우리는 호출하는 slice기본 객체 Array가 아닌 자사에 구현 하고 그게 왜 추가.prototype

var args = Array.prototype.slice.call(arguments);