1.手写call和apply
webVueBlog opened this issue · 0 comments
webVueBlog commented
call的场景是什么呢?每次写一个api,肯定得先知道他的用途才可以。
一句话介绍call:call()方法在使用 一个指定的this值 和 “若干个”指定的参数值 的前提下调用某个函数或方法。
var foo = {
value: 'dada'
};
function bar() {
console.log(this.value);
};
bar.call(foo); // dada;
bar(foo); // undefined;
注意两点:
- call改变了this的指向,指向到foo
- bar函数执行了
模拟一下:
思路:
- 将函数设为对象的属性
- 执行该函数
- 删除该函数
// 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的使用
- 函数原型上的方法
- call,apply第一个参数都是上下文 改变this指向
- call第二个参数开始,接受数组展开项目
- apply第二个参数开始,接受一个数组
- 返回值:返回 调用函数的返回值
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;
}