답변:
후드 아래에서 발생하는 .slice()
것은 정상적으로 호출 될 때 this
배열이며 배열을 반복하고 작업을 수행한다는 것입니다.
함수 this
에서 어떻게 .slice()
배열입니까? 당신이 할 때 :
object.method();
...는 object
자동의 값이된다 this
하여 method()
. 따라서 :
[1,2,3].slice()
... [1,2,3]
배열은 this
in 의 값으로 설정됩니다 .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()
for-in
순서를 보장하지 않는 진술입니다. 에 의해 사용되는 알고리즘 은 주어진 객체 (또는 Array 등 )로 .slice()
시작 0
하고 끝나는 (비 포함) 숫자 순서 를 정의합니다 .length
. 따라서 순서는 모든 구현에서 일관성이 보장됩니다.
var obj = {2:"two", 0:"zero", 1: "one"}
. for-in
객체를 열거하는 데 사용 하면 순서를 보장 할 수 없습니다. 그러나를 사용하면 for
수동으로 주문을 시행 할 수 있습니다 for (var i = 0; i < 3; i++) { console.log(obj[i]); }
. 이제 객체의 속성이 for
루프에 의해 정의 된 오름차순으로 표시됩니다 . 그게 뭐야 .slice()
. 실제 배열이 있는지는 중요하지 않습니다. 그냥 시작 0
하고 오름차순 루프의 속성에 액세스합니다.
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
.
prototype
합니까? 되지는 slice
기본 Array
방법은?
Array
생성자 함수이며, 해당 "클래스"입니다 Array.prototype
. 다음을 사용할 수도 있습니다[].slice
slice
는 각 Array
인스턴스 의 메서드 이지만 Array
생성자 함수는 아닙니다 . prototype
생성자의 이론적 인스턴스 메소드에 액세스 하는 데 사용 합니다.
먼저 JavaScript에서 함수 호출이 작동하는 방식 을 읽어야 합니다 . 혼자서도 귀하의 질문에 대답하기에 충분하다고 생각합니다. 그러나 여기에 무슨 일이 일어나고 있는지 요약되어 있습니다.
Array.prototype.slice
추출물 방법 에서 의 프로토 타입 . 그러나 메서드 (함수가 아님) 이므로 컨텍스트 (호출 객체 ) 가 필요하므로 직접 호출하면 작동 하지 않습니다 . 그렇지 않으면 throw 됩니다.slice
Array
this
Uncaught 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];
당신이 가지고 있다고 가정 해 봅시다. function.apply(thisArg, argArray )
apply 메소드는 함수를 호출하여 이것에 바인딩 될 객체와 선택적 인수 배열을 전달합니다.
slice () 메서드는 배열의 일부를 선택하고 새 배열을 반환합니다.
따라서 Array.prototype.slice.apply(arguments, [0])
배열 슬라이스 메소드를 호출하면 인수에 대해 호출 (바인드)됩니다.
어쩌면 조금 늦었지만이 혼란에 대한 대답은 call ()이 JS에서 상속을 위해 사용된다는 것입니다. 예를 들어 이것을 파이썬이나 PHP와 비교하면 call은 각각 super ()로 사용됩니다. init () 또는 parent :: _ construct ().
다음은 모두를 명확하게하는 사용법의 예입니다.
function Teacher(first, last, age, gender, interests, subject) {
Person.call(this, first, last, age, gender, interests);
this.subject = subject;
}
참조 : https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance
.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"]
나는 단지 나 자신을 생각 나게하기 위해 이것을 쓰고있다 ...
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);
});
}