Chrome 59 업데이트 : 아래 답변에서 예상했듯이 새로운 최적화 컴파일러를 사용하면 bind가 더 이상 느려지지 않습니다. 세부 정보가있는 코드는 다음과 같습니다. https://codereview.chromium.org/2916063002/
대부분의 경우 중요하지 않습니다.
.bind
병목 현상이 있는 응용 프로그램을 만드는 경우 가 아니라면 신경 쓰지 않을 것입니다. 가독성은 대부분의 경우 순수한 성능보다 훨씬 더 중요합니다. 네이티브를 사용하면 .bind
일반적으로 더 읽기 쉽고 유지 관리가 가능한 코드가 제공 된다고 생각합니다 . 이는 큰 장점입니다.
그러나 예, 중요한 경우- .bind
더 느립니다.
예, .bind
클로저보다 상당히 느립니다. 적어도 Chrome에서는 v8
. 개인적으로 성능 문제 때문에 Node.JS로 전환해야했습니다 (보다 일반적으로 성능 집약적 인 상황에서는 클로저가 다소 느립니다).
왜? 때문에 .bind
알고리즘은 더 많은 다른 기능을 갖는 기능을 배치하고 사용하는 것보다 복잡 .call
하거나 .apply
. (재미있는 사실은 toString이 [native function]으로 설정된 함수도 반환합니다.)
스펙 관점과 구현 관점에서이를 보는 방법에는 두 가지가 있습니다. 둘 다 관찰합시다.
- Target을 this 값으로 둡니다.
- IsCallable (Target)이 false이면 TypeError 예외를 발생시킵니다.
- A를 thisArg (arg1, arg2 등) 다음에 제공되는 모든 인수 값의 새로운 (비어있을 수 있음) 내부 목록을 순서대로 지정합니다.
...
(21. 인수 "arguments", PropertyDescriptor {[[Get]] : thrower, [[Set]] : thrower, [[Enumerable]] : false, [[Configurable])를 사용하여 F의 [[DefineOwnProperty]] 내부 메서드 호출) ] : false} 및 false.
(22. 반환 F.
랩보다 훨씬 복잡해 보입니다.
FunctionBind
v8 (Chrome JavaScript 엔진) 소스 코드를 확인해 보겠습니다 .
function FunctionBind(this_arg) {
if (!IS_SPEC_FUNCTION(this)) {
throw new $TypeError('Bind must be called on a function');
}
var boundFunction = function () {
"use strict";
if (%_IsConstructCall()) {
return %NewObjectFromBound(boundFunction);
}
var bindings = %BoundFunctionGetBindings(boundFunction);
var argc = %_ArgumentsLength();
if (argc == 0) {
return %Apply(bindings[0], bindings[1], bindings, 2, bindings.length - 2);
}
if (bindings.length === 2) {
return %Apply(bindings[0], bindings[1], arguments, 0, argc);
}
var bound_argc = bindings.length - 2;
var argv = new InternalArray(bound_argc + argc);
for (var i = 0; i < bound_argc; i++) {
argv[i] = bindings[i + 2];
}
for (var j = 0; j < argc; j++) {
argv[i++] = %_Arguments(j);
}
return %Apply(bindings[0], bindings[1], argv, 0, bound_argc + argc);
};
%FunctionRemovePrototype(boundFunction);
var new_length = 0;
if (%_ClassOf(this) == "Function") {
var old_length = this.length;
if ((typeof old_length === "number") &&
((old_length >>> 0) === old_length)) {
var argc = %_ArgumentsLength();
if (argc > 0) argc--;
new_length = old_length - argc;
if (new_length < 0) new_length = 0;
}
}
var result = %FunctionBindArguments(boundFunction, this,
this_arg, new_length);
return result;
여기 구현에서 많은 값 비싼 것들을 볼 수 있습니다. 즉 %_IsConstructCall()
. 이것은 물론 사양을 준수하는 데 필요하지만 많은 경우 간단한 랩보다 느리게 만듭니다.
또 다른 메모에서 호출 .bind
도 약간 다릅니다. 사양에 "Function.prototype.bind를 사용하여 생성 된 함수 개체에는 프로토 타입 속성이 없거나 [[Code]], [[FormalParameters]] 및 [[Scope]] 내부 속성 "