手写call、apply、bind
公共部分
function show(...args) {
console.log(this.name);
console.log(...args);
}
const person = {name: 'xyz'};
call
语法:
fn.call(obj,...args)
实现代码:
Function.prototype.myCall = function (obj, ...args) {
// 在这里判断是否有obj
obj= obj|| window
/*给obj添加一个属性fn,并把要改变指向的函数赋值给他这里的this是show,那么obj.fn = show */
obj.fn = this;
//调用obj中的show,并且把参数传递进去,把他保存在result中
const result = obj.fn(...args);
// 因为obj是另一个函数或者对象,所以不能改变他原来的结构,把fn属性用完删掉 delete obj.fn;
//返回执行结果
return result;
}
show.myCall(person, 1, 2, 3); //xyz 123
apply
语法:
fn.apply(obj,[...args])
注意点:
apply第二个参数接收的是一个数组。将要传的数据放入数组中,如果不是数组就会报错。其他的和call差不多。
代码实现:
Function.prototype.myApply = function (obj, args = []) {
//因为也可以不传参数,所以可以先给第二个参数赋值个空数组
// 判断是否是一个数组
if (args && !Array.isArray(args)){
throw new Error('这不是一个数组')
}
obj= obj|| window
obj.fn = this;
const result = obj.fn(...args);
delete obj.fn;
return result;
}
show.myApply(person,["xyz","zxy"]); // xyz xyz zxy
bind
语法:
fn.bind(obj,...args)()
bind的注意点:
- 不会立即执行会返回一个新函数
- 柯里化特征
- 返回的新函数可以实例化
这几点就比较麻烦了,所以比较call和apply比较难理解一点。
Function.prototype.myBind = function (obj, ...args1) {
// 拿到要修改this,就是show函数
const that = this;
//这里的o就是个跳板
const o = function () {};
// 因为bing是会返回的,不是立即执行的
const newFn = function (...args2) {
// 将参数合并到一个数组
const args = args1.concat(args2);
// 因为bind可以返回后,手动执行,并且可以实例化
//所以我们要判断this的指向,如果返回过去实例化了,就用实例化后的this
if (this instanceof o) {
that.apply(this, args);
} else {
// 如果没有就用原来的
that.apply(obj, args);
}
}
// 还要把原型给改下
o.prototype = that.prototype;
newFn.prototype = new o;
return newFn;
}
show.myBind(person, 5, 6)(2, 1); // xyz 5 6 2 1
new的过程
公共部分
function Person(name) {
this.name = name
}
new的注意点:
如果是构造函数里面return 的是一个对象,那么new出来的就是这个对象
function Person(name) {
this.name = name
return {
age:23
}
}
let a = new Person('xyz')
console.log(a);
代码实现:
function myNew(myObj,...args) {
// new就是先创建一个对象
let obj = {}
// 将实例的__proto__指向构造函数的prototype
obj.__proto__ = myObj.prototype
// 利用apply给父类的属性赋值
// 如果里面返回的是一个对象那么myObj.apply(obj,args)就是返回的那个对象,如果没有就是返回的undefined
let result = myObj.apply(obj,args)
// 那么实例拿到的就是这个对象,所以在return的时候判断下
// 如果是return的对象,那么返回result如果没有就返回obj
return result instanceof Object ? result : obj
}
let a = myNew(Person,"xyz")
console.log(a.name); // xyz
instanceof
公共部分
function Person(name) {this.name = name}
let a = new Person('xyz')
instanceof依靠的是原型链进行判断
代码实现:
function myInstanceof (left,right) {
let rightValue = right.prototype
left = left.__proto__
while (true){
if (left === null){
return false
}else if (left === rightValue){
return true
}
left = left.__proto__
}
}
myInstanceof(a,Person) //true
小结
学习前端一年多了,平时都是看看别人的文章。这些都是当时学习js自己看文章,加上自己的理解。第一次写有什么不足之处,希望大家评论区留言😊