자바스크립트의 메소드 차용에 대한 자세한 소개를 살펴보겠습니다. 참고: 이 기사에서는 call(), apply() 및 바인딩() 사용에 대한 관련 지식과 이들 간의 차이점을 숙지했다고 가정합니다. JavaScript로 대출하는 방법을 알려드릴 수 있습니다.
머리말
call(), apply(), 바인딩() 메소드를 통해 다른 객체로부터 메소드를 상속받지 않고도 쉽게 빌릴 수 있습니다.
JavaScript에서 메서드 대여
JavaScript에서는 개체 자체나 프로토타입에 반드시 정의할 필요가 없는 다른 개체의 함수나 메서드를 재사용하는 것이 가능한 경우가 있습니다. call(), apply() 및 바인딩() 메소드를 통해 다른 객체를 상속받지 않고도 다른 객체의 메소드를 쉽게 빌릴 수 있습니다. 이는 전문 JavaScript 개발자가 사용하는 일반적인 접근 방식입니다.
프로토타입 메서드
JavaScript에서는 문자열, 숫자, 부울과 같은 불변의 기본 데이터 유형을 제외하고 거의 모든 데이터가 객체입니다. 배열은 순서가 지정된 시퀀스를 순회하고 변환하는 데 적합한 개체입니다. 해당 프로토타입에는 슬라이스, 조인, 푸시 및 팝과 같은 유용한 메서드가 있습니다.
일반적인 예는 객체와 배열이 모두 목록 유형 데이터 구조인 경우 객체가 배열에서 메서드를 "빌려올" 수 있다는 것입니다. 가장 일반적으로 차용되는 메서드는 Array.prototype.slice
입니다. Array.prototype.slice
。
function myFunc() { // error, arguments is an array like object, not a real array arguments.sort(); // "borrow" the Array method slice from its prototype, which takes an array like object (key:value) // and returns a real array var args = Array.prototype.slice.call(arguments); // args is now a real Array, so can use the sort() method from Array args.sort(); } myFunc('bananas', 'cherries', 'apples');
借用方法之所以可行,是因为 call 和 apply 方法允许在不同上下文中调用函数,这也是重用已有功能而不必继承其它对象的好方法。实际上,数组在原型中定义了很多常用方法,比如 join 和 filter 也是:
// takes a string "abc" and produces "a|b|c Array.prototype.join.call('abc', '|'); // takes a string and removes all non vowels Array.prototype.filter.call('abcdefghijk', function(val) { return ['a', 'e', 'i', 'o', 'u'].indexOf(val) !== -1; }).join('');
可以看出,不仅对象可以借用数组的方法,字符串也可以。但是因为泛型方法是在原型上定义的,每次想要借用方法时都必须使用 String.prototype
或 Array.prototype
。这样写很啰嗦,很快就会令人生厌。更有效的方法是使用字面量来达到同样的目的。
使用字面量借用方法
字面量是一种遵循JavaScript规则的语法结构,MDN 这样解释:
在JavaScript中,使用字面量可以代表值。它们是固定值,不是变量,就是在脚本中按字面给出的。
字面量可以简写原型方法:
[].slice.call(arguments); [].join.call('abc', '|'); ''.toUpperCase.call(['lowercase', 'words', 'in', 'a', 'sentence']).split(',');
这样看上去没有那么冗长了,但是必须直接在 [] 和 "" 上操作以借用方法,仍然有点丑。可以利用变量保存对字面量和方法的引用,这样写起来更简便些:
var slice = [].slice; slice.call(arguments); var join = [].join; join.call('abc', '|'); var toUpperCase = ''.toUpperCase; toUpperCase.call(['lowercase', 'words', 'in', 'a', 'sentence']).split(',');
有了借用方法的引用,我们就可以轻松地使用 call() 调用它了,这样也可以重用代码。秉着减少冗余的原则,我们来看看可否借用方法却不用每次调用都要写 call() 或者 apply():
var slice = Function.prototype.call.bind(Array.prototype.slice); slice(arguments); var join = Function.prototype.call.bind(Array.prototype.join); join('abc', '|'); var toUpperCase = Function.prototype.call.bind(String.prototype.toUpperCase); toUpperCase(['lowercase', 'words', 'in', 'a', 'sentence']).split(',');
如你所见,现在可以使用 Function.prototype.call.bind
来静态绑定从不同原型“借来的”方法了。但是 var slice = Function.prototype.call.bind(Array.prototype.slice)
这句话实际是如何起作用的呢?
理解 Function.prototype.call.bind
Function.prototype.call.bind
乍一看有些复杂,但是理解它是如何起作用的会非常有益。
Function.prototype.call
是一种引用,可以“call”函数并将设置其“this”值以在函数中使用。
注意“bind”返回一个存有其“this”值的新函数。因此 .bind(Array.prototype.slice)
var scoreCalculator = { getSum: function(results) { var score = 0; for (var i = 0, len = results.length; i < len; i++) { score = score + results[i]; } return score; }, getScore: function() { return scoreCalculator.getSum(this.results) / this.handicap; } }; var player1 = { results: [69, 50, 76], handicap: 8 }; var player2 = { results: [23, 4, 58], handicap: 5 }; var score = Function.prototype.call.bind(scoreCalculator.getScore); // Score: 24.375 console.log('Score: ' + score(player1)); // Score: 17 console.log('Score: ' + score(player2));
메소드 대여는 호출 및 적용 메소드를 통해 다양한 컨텍스트에서 함수를 호출할 수 있기 때문에 작동하며, 이는 다른 객체에서 상속하지 않고도 기존 기능을 재사용할 수 있는 좋은 방법이기도 합니다. 실제로 배열은 프로토타입에서 조인 및 필터와 같은 많은 일반적인 메서드를 정의합니다.
rrreee객체는 배열의 메서드뿐만 아니라 문자열도 빌릴 수 있다는 것을 알 수 있습니다. 하지만 일반 메서드는 프로토타입에 정의되어 있으므로 메서드를 빌릴 때마다 String.prototype
또는 Array.prototype
을 사용해야 합니다. 이런 식으로 글을 쓰는 것은 장황하고 금방 지루해질 수 있습니다. 보다 효율적인 방법은 동일한 목적을 달성하기 위해 리터럴을 사용하는 것입니다.
리터럴 차용 방법 사용
Literal은 JavaScript 규칙을 따르는 구문 구조입니다. MDN은 이를 다음과 같이 설명합니다.
JavaScript에서 리터럴을 사용하면 값을 나타낼 수 있습니다. 이는 변수이거나 스크립트에 문자 그대로 제공되는 고정 값입니다.
리터럴은 프로토타입 메서드를 축약할 수 있습니다.rrreee
별로 장황해 보이지는 않지만 메서드를 빌리려면 [] 및 ""에 직접 작업해야 하는 것은 여전히 약간 보기 흉합니다. 변수를 사용하여 리터럴 및 메소드에 대한 참조를 저장할 수 있으므로 작성이 더 쉽습니다.rrreee
rrreee🎜🎜🎜보다시피 이제함수 .prototype.call.bind
는 다른 프로토타입에서 "빌려온" 메서드를 정적으로 바인딩합니다. 그런데 var Slice = Function.prototype.call.bind(Array.prototype.slice)
문장이 실제로 어떻게 작동할까요? 🎜🎜🎜Function.prototype.call.bind 이해 🎜🎜🎜Function.prototype.call.bind
는 처음에는 복잡해 보일 수 있지만 작동 방식을 이해하면 매우 유익할 수 있습니다. 🎜🎜Function.prototype.call
은 함수를 "호출"하고 함수에서 사용할 "this" 값을 설정하는 참조입니다. 🎜"bind"는 "this" 값을 사용하여 새 함수를 반환합니다. 따라서 .bind(Array.prototype.slice)
에서 반환된 새 함수의 "this"는 항상 Array.prototype.slice 함수입니다. 🎜🎜🎜요약하자면, 🎜새 함수는 "call" 함수를 호출하고 "this"는 "slice" 함수를 호출합니다. Slice()를 호출하면 이전에 정규화된 메서드를 가리킵니다. 🎜🎜🎜🎜🎜사용자 정의 개체의 방법🎜🎜🎜🎜상속은 훌륭하지만 일반적으로 개발자는 일부 개체나 모듈 간의 공통 기능을 재사용하려고 할 때 상속을 사용합니다. 코드 재사용을 위해서만 상속을 사용할 필요는 없습니다. 대부분의 경우 간단한 메소드 차용은 복잡하기 때문입니다. 🎜🎜이전에는 네이티브 메소드 차용에 대해서만 논의했지만 어떤 메소드든지 차용이 가능합니다. 예를 들어 다음 코드는 포인트 게임에서 플레이어 점수를 계산할 수 있습니다. 🎜🎜🎜rrreee🎜🎜🎜위의 예는 매우 무뚝뚝하지만 기본 메서드와 마찬가지로 사용자 정의 메서드도 쉽게 빌릴 수 있음을 알 수 있습니다. 🎜🎜🎜요약🎜🎜🎜Call, Bind 및 Apply는 함수 호출 방식을 변경할 수 있으며 함수를 빌릴 때 자주 사용됩니다. 대부분의 개발자는 기본 메서드를 차용하는 데 익숙하지만 사용자 지정 메서드를 차용하는 경우는 적습니다. 🎜🎜위 내용은 제가 여러분을 위해 정리한 내용입니다. 앞으로 도움이 되길 바랍니다. 🎜🎜관련 기사: 🎜🎜🎜js에 내장된 Math의 속성과 메서드에 대해 자세히 이야기해 보세요(한 눈에 알 수 있음)🎜🎜🎜JavaScript를 사용하여 패턴 일치의 문자열 메서드 구현
위 내용은 JavaScript의 여러 대출 방법에 대한 자세한 설명(그래픽 튜토리얼)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!