development

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

big-blog 2020. 2. 16. 20:44
반응형

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]배열의 값으로서 설정된다 this에서 .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.


// 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]

먼저 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);

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);

이 동작의 저수준 기본 사항은 JS 엔진에 완전히 통합 된 유형 캐스팅이라는 것을 잊지 마십시오.

슬라이스는 단지 기존의 arguments.length 속성으로 인해 객체를 가져 와서 모든 작업을 수행 한 후에 캐스팅 된 배열 객체를 반환합니다.

String-method를 INT 값으로 처리하려고 시도 할 때 테스트 할 수있는 동일한 논리 :

String.prototype.bold.call(11);  // returns "<b>11</b>"

그리고 그것은 위의 진술을 설명합니다.


그것은 slice배열을 가지고 메소드를 사용하고 그것을 객체 this호출 arguments합니다. 즉, 그러한 메소드 arguments.slice()있다고 가정 한 것처럼 호출합니다 arguments.

인수없이 슬라이스를 만들면 모든 요소가 사용되므로 요소를 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);
    });
}

참고 URL : https://stackoverflow.com/questions/7056925/how-does-array-prototype-slice-call-work



반응형