Call
call():在使用一个指定的this值和若干个指定的参数值的前提下调用摸个函数或方法
例:
const foo = {
name: 'xiaohu'
}
function a() {
console.log(this.name)
}
a.call(foo) // 输出: xiaohu
第一步
上述方法等于:
const foo = {
name: 'xiaohu',
a: function () {
console.log(this.name)
}
}
foo.a()
所以我们可以这样
Function.prototype.myCall = function(vm){
vm.fn = this;
vm.fn()
delete vm.fn
}
// 测试一下
let foo = {
age:'16'
}
function a(){
console.log(this.age)
}
a.myCall(foo) //out:16
第二步
call除了可以指定this,还可以指定参数
Function.prototype.myCall = function(vm,...rest){
vm.fn = this;
vm.fn(...rest)
delete vm.fn
}
// 测试一下
let foo = {
age:'16'
}
function a(name){
console.log(name)
console.log(this.age)
}
a.myCall(foo,'xiaohu') //out:xiaohu 16
第三步
当this为null或者undefined时,this指向window,且函数有返回值
Function.prototype.myCall = function (vm, ...rest) {
if (typeof vm === 'undefined' || vm === null) {
vm = globalThis
}
const fnSyb = Symbol()
vm[fnSyb] = this;
const res = vm[fnSyb](...rest)
delete vm[fnSyb]
return res
}
Apply
几乎跟call一致,只不过第二个参数是传递数组
Function.prototype.myApply = function(vm,args){
if (typeof vm === 'undefined' || vm === null) {
vm = globalThis
}
const fnSyb = Symbol()
vm[fnSyb] = this;
const res = vm[fnSyb](...rest)
delete vm[fnSyb]
return res
}
Bind
需要注意的是bind可以作为构造函数使用
Function.prototype.bind = function (vm, ...arg) {
if (typeof this !== 'function') return
const that = this
const res = function (...args) {
that.myApply(this instanceof res ? this : vm, arg.concat(args))
}
res.prototype = this.prototype
return res
}
New
因为new是作为js的关键字,我们这边用函数来代替实现 我们还需要判断构造函数的返回值是不是一个对象,如果是就返回,没有该返回什么返回什么
function myNew(vm, ...rest) {
const obj = new Object();
const Constructor = vm;
obj.__proto__ = Constructor;
const res = Constructor.myApply(obj, rest)
return typeof res === 'object' ? res : obj
}