foreword
Speaking of handwriting apply, call and other methods are common problems in face-to-face interviews. In fact, I have never encountered them in interviews, but if I have not encountered them, it does not mean that I do not need to master them. These should only be tested by big factories. As an ordinary person who graduated from both non-graduates, he still has a dream of entering a big factory. What if one day it comes true? Once a person loses his dream, what is the difference from a salted fish. Today, I will take everyone to realize the simple version of call and apply.
apply
Regarding apply
the definition of , I actually didn’t find relevant information on the Internet. What I found was the difference apply
between usage and call
. What I understand is to change the execution context this point in the execution function and execute the function . So what we need to achieve is actually only two points:
1. Change the this point of the function.
2. If the function has parameters, we pass in the function parameters.
// 改变函数this指向 我们应该从Function原型上入手
Function.prototype.myApply = (context) { // context表示函数传入的执行上下文
if(typeof this !== 'function' ) { // 调用apply的应该是一个函数,this就是调用apply的函数
throw new Error('type Error')
}
if (context === null || context === undefined) {
context = window // 执行上下文不存在时直接指向全局window
} else {
context = Object(context) // 值为原始值(Number,Boolean,String),this指向其实例对象 引用类不变
}
const fnSymbol = Symbol()
context[fnSymbol] = this
context[fn] = this // 其实这儿用fn表好理解,这儿用Symbol是为了防止调用函数的对象中有fn属性。
const args = arguments[1] // 获取参数
// apply的第二个参数是数组, 记住appy和array对应就行了 之前老师记不住
const result = args.length > 1 ? context[fnSymbol](...args) : context[fnSymbol]()
delete context[fnSymbol]
return result
}
Next, let's verify the difference between our handwritten apply and the original execution result. Here we only verify the most basic usage. I don't know how to use advanced ones, let alone implement them.
const obj = {
data: [1, 3, 4],
add: function (a, b, c) {
return a + b + c
}
}
const add = obj.add;
const res = add.myApply(obj, obj.data)
const res1 = add.apply(obj,obj.data)
console.log(res,res1) // 8 8
call
call
The implementation is apply
almost the same, the only thing to note is that call
when receiving function parameters, they are passed in one by one.
Function.prototype.myCall = function(context) {
if (typeof this !== 'function'){
console.log('type Error')
}
if (context === null && context === undefined){
context = window // 若执行上下文为空直接指向全局window
}else {
context = Object(context) // 基础数据类型转化为实例对象
}
const fnSymbol = Symbol()
context[fnSymbol] = this;
const args = [...arguments].slice(1) // 这里使用结构获取函数传入的所有参数。
const result = context[fnSymbol](...args)
delete context[fnSymbol]
return result
}
// 验证
const obj = {
data: [1, 3, 4],
add: function (a, b, c) {
return a + b + c
}
}
const add = obj.add;
const res = add.myCall(obj, ...obj.data)
const res1 = add.call(obj, ...obj.data)
console.log(res,res1) // 8 8
at last
There is also the most difficult bind
manual implementation, which is a bit difficult. I haven't figured it out myself, so I won't come out to make a fool of myself. I will set a flag first, and I will come back to make it up when I figure it out.