이 문서에서는 JS에서 기본적으로 호출, 적용 및 바인딩을 구현하는 방법을 공유합니다. 필요한 친구가 참조할 수 있습니다.
여기서 지적한 문제와 관련이 있기 때문에 call, Apply, Bind의 사용법은 진부하다고 할 수 있습니다. 이 기사의 주요 기능은 js 기본 메소드를 사용하여 세 가지 메소드를 구현하고 원리를 이해하며 관련 지식 포인트를 더 잘 이해하는 것입니다. Github 주소 호출, 적용 및 바인딩
의 기본 구현 간략한 소개: 호출 및 적용 메소드는 모두 지정된 이 값과 해당 매개변수를 사용하여 함수 또는 메소드를 호출합니다. 차이점은 호출이 여러 매개변수를 전달하는 반면 적용은 배열을 전달한다는 것입니다.
예:
var obj = { name: 'linxin' } function func(age, sex) { console.log(this.name,age,sex); } func.call(obj,12,'女'); // linxin 12 女 func.apply(obj, [18, '女']); //linxin 18 女
아이디어: JavaScript의 this 포인터는 다음과 같이 말합니다. 함수는 객체의 메서드로 호출될 수도 있으며, 이 경우 상위 객체를 참조합니다. 우리가 흔히 말하는 것이 누구에게 전화하든 이것이 가리킬 것입니다. 따라서 구현 방법은 들어오는 개체에 이러한 메서드를 추가한 다음 이 메서드를 실행하는 것입니다. 객체의 지속성을 유지하기 위해 객체는 실행 후 삭제됩니다. 아주 간단하지 않나요^-^.
첫 번째 경험:
Function.prototype.newCall = function(context) { context.fn = this; // 通过this获取call的函数 context.fn(); delete context.fn; } let foo = { value: 1 } function bar() { console.log(this.value); } bar.newCall (foo); // 1
이렇게 하면 기본 버전 구현이 완료되는데, 전달해야 할 매개변수가 있다면 어떨까요?
따라서 전달된 매개변수의 수가 불확실하기 때문에 이를 최적화할 수 있으며 상대적으로 간단한 Arguments 객체에서 이를 얻을 수 있습니다. 문제는 매개변수가 불확실하다는 것입니다. 실행하려는 함수에 매개변수를 어떻게 전달합니까? 여기에는 두 가지 옵션이 있습니다. 하나는 eval splicing을 이용하는 것이고, 다른 하나는 es6을 사용하는 것입니다.
경험 업그레이드(평가판):
Function.prototype.newCall = function(context) { context.fn = this; var args = []; for(var i = 1, len = arguments.length; i < len; i++) { args.push('arguments[' + i + ']'); } eval('context.fn(' + args +')'); delete context.fn; } let person = { name: 'Abiel' } function sayHi(age,sex) { console.log(this.name, age, sex); } sayHi.newCall (person, 25, '男'); // Abiel 25 男
경험 업그레이드(ES6 버전):
Function.prototype.newCall = function(context) { context.fn = this; context.fn(...Array.from(arguments).slice(1)); delete context.fn; } let person = { name: 'Abiel' } function sayHi(age,sex) { console.log(this.name, age, sex); } sayHi.newCall (person, 25, '男'); // Abiel 25 男
ES6 메서드는 인수를 사용하지 않고 구현할 수 있습니다.
ES6 버전을 다시 업그레이드하세요.
Function.prototype.newCall = function(context, ...parameter) { context.fn = this; context.fn(...parameter); delete context.fn; } let person = { name: 'Abiel' } function sayHi(age,sex) { console.log(this.name, age, sex); } sayHi.newCall (person, 25, '男'); // Abiel 25 男
이 방법으로 우리는 기본적으로 통화 기능을 구현했지만 여전히 숨겨진 위험과 차이점이 있습니다.
객체 자체에 fn 메소드가 있으면 큰 문제가 발생합니다.
호출로 전달된 객체가 null이거나 다른 유형인 경우 함수는 오류를 보고합니다.
궁극적 경험:
Function.prototype.newCall = function(context, ...parameter) { if (typeof context === 'object') { context = context || window } else { context = Object.create(null) } let fn = Symbol() context[fn] = this context[fn](...parameter); delete context[fn] } let person = { name: 'Abiel' } function sayHi(age,sex) { console.log(this.name, age, sex); } sayHi.newCall (person, 25, '男'); // Abiel 25 男
call 구현 후 Apply도 같은 아이디어를 가지고 있습니다.
적용 구현:
Function.prototype.newApply = function(context, parameter) { if (typeof context === 'object') { context = context || window } else { context = Object.create(null) } let fn = Symbol() context[fn] = this context[fn](parameter); delete context[fn] }
bind도 함수 메서드이며 이 함수의 실행을 변경하는 것이며 여러 매개변수를 전달할 수도 있습니다. 호출 및 적용과 달리 바인드 메소드는 즉시 실행되지 않지만 이 포인터의 컨텍스트를 변경하는 함수를 반환합니다. 원래 함수는 변경되지 않았습니다. 그리고 함수 자체가 이 객체에 바인딩된 함수인 경우 Apply 및 Call은 예상대로 실행되지 않습니다.
첫 번째 경험:
Function.prototype.bind = function (context) { var me = this return function () { // bind之后得到的函数 return me.call(context) // 执行是改变this执行 } }
추가된 매개변수:
Function.prototype.bind = function (context,...innerArgs) { var me = this return function (...finnalyArgs) { return me.call(context,...innerArgs,...finnalyArgs) } } let person = { name: 'Abiel' } function sayHi(age,sex) { console.log(this.name, age, sex); } let personSayHi = sayHi.bind(person, 25) personSayHi('男')
관련 권장 사항:
JS 상속에 대한 자세한 소개(프로토타입 체인, 생성자, 조합, 프로토타입, 기생, 기생 조합, 클래스 확장)
위 내용은 js에서 기본적으로 호출, 적용 및 바인딩을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!