小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
想要真正了解一个事物,最好方法就是自己动手实现一个,今天通过自己实现一个 call 和 apply 给大家介绍如何理解和使用 call 和 apply 来调用函数。
const tut = {
title:"machine learning"
};
function getTitle(){
console.log(`title: ${this.title}`)
}
getTitle.call(tut);
复制代码
定义一个对象 tut
然后在定义个函数 getTitle
,直接执行getTitle()
函数,this
是指向 window
。用 call
调用函数 getTitle
就会将 this
绑定到 tut
对象上。 所以输出时候就可以用上对象属性 title
。
要了解 call 我们就来创建一个 call
要理解 call 方法如何使用,以及其背后到底发生了什么,最好方法就是自己去实现一个 call 方法。
const tut = {
title:"machine learning"
}
function description(){
console.log(`title: ${this.title}`)
}
Function.prototype.newCall = function(obj){
console.log(this);
}
description.newCall(tut);
复制代码
index.js:10 ƒ description(){
console.log(`title: ${this.title}`)
}
复制代码
因为这是还没有将 tut
绑定到 this
,所以这时this
现在还是 description
函数本身。
Function.prototype.newCall = function(obj){
obj.tmp = this;
obj.tmp();
// console.log(this);
delete obj.tmp;
}
复制代码
function description(subTitle,summay,type){
console.log(`title: ${this.title}`);
console.log(subTitle,summay,type);//undefined undefined undefined
}
...
description.newCall(tut,'machine learning','summary','video');
复制代码
const tut = {
title:"machine learning"
}
function description(subTitle,summay,type){
console.log(`title: ${this.title}`)
console.log(subTitle,summay,type);
}
Function.prototype.newCall = function(obj){
var obj = obj || window
obj.tmp = this;
var newArguments = [];
for (let i = 1; i < arguments.length; i++) {
newArguments.push('arguments[' + i +']');
}
console.log(newArguments)
eval('obj.tmp(' + newArguments + ')');
// console.log(this);
delete obj.tmp;
}
description.newCall(null,'machine learning','summary','video');
复制代码
const tut = {
title:"machine learning"
}
function description(subTitle,summay,type){
// console.log(`title: ${this.title}`)
// console.log(subTitle,summay,type);
return {
title:this.title,
subTitle:subTitle,
summay:summay,
type:type
}
}
Function.prototype.newCall = function(obj){
var obj = obj || window
obj.tmp = this;
var newArguments = [];
for (let i = 1; i < arguments.length; i++) {
newArguments.push('arguments[' + i +']');
}
console.log(newArguments)
const result = eval('obj.tmp(' + newArguments + ')');
// console.log(this);
delete obj.tmp;
return result;
}
const res = description.newCall(tut,'machine learning','summary','video');
console.log(res)//{title: 'machine learning', subTitle: 'machine learning', summay: 'summary', type: 'video'}
复制代码
aplly 的实现
apply 方法与 call 比较类似,第一个参数是调用方法的对象,第二个参数是参数数组,apply 实现了 call 比较类似,我先把代码呈现在这里,大家应该一看就懂。
const tut = {
title:"machine learning"
}
function description(subTitle,summay,type){
console.log(`title: ${this.title}`)
console.log(subTitle,summay,type);
// return {
// title:this.title,
// subTitle:subTitle,
// summay:summay,
// type:type
// }
}
Function.prototype.newApply = function(obj,arr){
var obj = obj || window
obj.tmp = this;
if(!arr){
obj.tmp()
}else{
var newArguments = [];
for (let i = 0; i < arr.length; i++) {
newArguments.push('arr[' + i +']');
}
const result = eval('obj.tmp(' + newArguments + ')');
}
delete obj.tmp;
}
description.newApply(tut,['machine learning','summary','video']);
复制代码