>  기사  >  웹 프론트엔드  >  js에서 기본적으로 호출, 적용 및 바인딩을 구현하는 방법

js에서 기본적으로 호출, 적용 및 바인딩을 구현하는 방법

不言
不言원래의
2018-07-23 11:26:582059검색

이 문서에서는 JS에서 기본적으로 호출, 적용 및 바인딩을 구현하는 방법을 공유합니다. 필요한 친구가 참조할 수 있습니다.

여기서 지적한 문제와 관련이 있기 때문에 call, Apply, Bind의 사용법은 진부하다고 할 수 있습니다. 이 기사의 주요 기능은 js 기본 메소드를 사용하여 세 가지 메소드를 구현하고 원리를 이해하며 관련 지식 포인트를 더 잘 이해하는 것입니다. Github 주소 호출, 적용 및 바인딩

call 및 Apply

의 기본 구현 간략한 소개: 호출 및 적용 메소드는 모두 지정된 이 값과 해당 매개변수를 사용하여 함수 또는 메소드를 호출합니다. 차이점은 호출이 여러 매개변수를 전달하는 반면 적용은 배열을 전달한다는 것입니다.
예:

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

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 상속에 대한 자세한 소개(프로토타입 체인, 생성자, 조합, 프로토타입, 기생, 기생 조합, 클래스 확장)

위 내용은 js에서 기본적으로 호출, 적용 및 바인딩을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.