Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.手写call和apply #3

Open
webVueBlog opened this issue May 20, 2022 · 0 comments
Open

1.手写call和apply #3

webVueBlog opened this issue May 20, 2022 · 0 comments

Comments

@webVueBlog
Copy link
Owner

webVueBlog commented May 20, 2022

call的场景是什么呢?每次写一个api,肯定得先知道他的用途才可以。

一句话介绍call:call()方法在使用 一个指定的this值 和 “若干个”指定的参数值 的前提下调用某个函数或方法。

var foo = {
 value: 'dada'
};

function bar() {
 console.log(this.value);
};

bar.call(foo); // dada;
bar(foo); // undefined;

注意两点:

  1. call改变了this的指向,指向到foo
  2. bar函数执行了

模拟一下:

思路:

  1. 将函数设为对象的属性
  2. 执行该函数
  3. 删除该函数
// call()手写
Function.prototype.myCall = function(context) {
 // 判断参数context 如果不存在 则为window;
 context = context || window;

 // 赋值函数 this
 context.func = this;

 // 获取参数
 let args = [...arguments].slice(1);

 // 获取结果
 let result = context.func(...args);

 // 删除属性
 delete context.func;

 // 返回结果
 return result;
}
// 手写apply
Function.prototype.myApply = function(context) {
 context = context || window;
 context.func = this;

 let result
 if(arguments[1]) {
  result = context.func(...arguments[1]);
 } else {
  result = context.func();
 }
 
 delete context.func;
 return result;
}
// 手写apply
Function.prototype.myApply = function(context, args) {
 context = context || window;
 context.func = this;

 let result = null;
 if(args.length === 0) {
  result = context.func();
 } else {
  result = context.func(...args);
 }

 delete context.func;
 return result;
}

call的实现:

Function.prototype.myCall = function(context, ...arguments) {
 context = context || window; // call不传值默认为window
 context.func = this;
 const result = context.func(...arguments);
 delete context.func;
 return result;
};

apply的实现:

Function.prototype.myApply = function(context, ...arguments) {
 context = context || window;
 context.func = this;
 arguments = arguments || [];
 let result = context.func(...arguments);
 delete context.fn;
 return result;
}

call和apply的使用

  1. 函数原型上的方法
  2. call,apply第一个参数都是上下文 改变this指向
  3. call第二个参数开始,接受数组展开项目
  4. apply第二个参数开始,接受一个数组
  5. 返回值:返回 调用函数的返回值
interface ThisArg {
 fn: Function
}

declare global {
 interface Winodw {
  fn: Function
 }
}

function Call(thisArg: ThisArg, ...args: any[]) {
 const context = thisArg || window
 context.fn = this
 const result = thisArg.fn(...args)
 delete thisArg.fn
 return result
}

function Apply(thisArg: ThisArg, args: any[]) {
 const context = thisArg || window
 context.fn = this

 let result
 
 if(!args.length) {
  result = context.fn()
 } else {
  result = contextfn(...args)
 }
 
 delete thisArg.fn
 return result
}

实现思想,通过 object 中函数 可以改变 this 的指向

const obj = {
 value: 'dada',
 func: function() {
  console.log(this.value);
 }
}
obj.func(); // dada

默认值:

Function.prototype.myCall = function(context = window, ...args) {
 const fnKey = Symbol('fn');
 context[fnKey] = this;
 const result = context[fnKey](...args);
 delete context[fnKey];
 return result;
}
Function.prototype.myApply = function(context = window, args=[]) {
 const fnKey = Symbol('fn');
 context[fnKey] = this;
 const result = context[fnKey](...args);
 delete context[fnKey];
 return result;
}

简写版本的call和apply手写 💯

Function.prototype.myCall = function(context) {
 const context = Object(context) || window;
 context.fn = this;
 let args = [];
 for(let i = 1, len = arguments.length; i < len; i++) {
  args.push('arguments[' + i + ']');
 }
 var result = eval('context.fn(' + args + ')‘);
 delete context.fn;
 return result;
}
Function.prototype.myApply = function(context, arr) {
 const const = Object(context) || window;
 context.fn = this;
 let result;
 if(!arr) {
  result = context.fn();
 } else {
  let args = [];
  for(let i = 0, len = arr.length; i < len; i++) {
   args.push('arr[' + i + ']');
  }
  result = eval('context.fn(' + args + ')');
 }
 delete context.fn;
 return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant