- 小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
前言
面试时被问:如何用js自己实现一个Function.prototype.call来修改function中this?
call的基本概念
注意: 该方法的语法和作用与
apply()方法类似,只有一个区别,就是call()方法接受的是一个参数列表,而apply()方法接受的是一个包含多个参数的数组。
call的基本用法
function zz(name) {
console.log(this);
console.log(name, this.name)
};
let a = {
name: 234
}
zz.call(a, ["abc", "2332"]);
//打印值 {name, 234},
// ["abc", "2332"], 234
zz();
//打印值 window
//underfined underfined
手写call
Function.prototype.myCall = function(context,...args){
let cxt = context || window;
//将当前被调用的方法定义在cxt.func上.(为了能以对象调用形式绑定this)
//新建一个唯一的Symbol变量避免重复
let func = Symbol()
cxt[func] = this;
args = args ? args : []
//以对象调用形式调用func,此时this指向cxt 也就是传入的需要绑定的this指向
const res = args.length > 0 ? cxt[func](...args) : cxt[func]();
//删除该方法,不然会对传入对象造成污染(添加该方法)
delete cxt[func];
return res;
}
apply的基本概念
call()方法的作用和 apply() 方法类似,区别就是
call()方法接受的是参数列表,而apply()方法接受的是一个参数数组。
apply的用法
function zz(name, age) {
console.log(this);
console.log(name,age, this.name)
};
let a = {
name: 234
}
zz.apply(a, ["abc", "2332"]);
apply 常见的案例
const arr = [10, 16, 23, 6, 16];
const max = Math.max.apply(Math, arr); // 23
const min = Math.min.apply(Math, arr); // 6
手写apply
Function.prototype.myApply = function(context,args = []){
let cxt = context || window;
//将当前被调用的方法定义在cxt.func上.(为了能以对象调用形式绑定this)
//新建一个唯一的Symbol变量避免重复
let func = Symbol()
cxt[func] = this;
//以对象调用形式调用func,此时this指向cxt 也就是传入的需要绑定的this指向
const res = args.length > 0 ? cxt[func](...args) : cxt[func]();
delete cxt[func];
return res;
}
bind的基本概念
bind的基础用法
const module = {
x: 42,
getX: function() {
return this.x;
}
};
const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// expected output: undefined
const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42
bind的实现
Function.prototype.myBind = function (context, ...args) {
//新建一个变量赋值为this,表示当前函数
const fn = this
//判断有没有传参进来,若为空则赋值[]
args = args ? args : []
//返回一个newFn函数,在里面调用fn
return function newFn(...newFnArgs) {
if (this instanceof newFn) {
return new fn(...args, ...newFnArgs)
}
return fn.apply(context, [...args,...newFnArgs])
}
}