1.call 函数的实现步骤:
引入:
function person() {
console.log(this.name);
}
var egg = {name:'蛋老师'};
person.call(egg); //函数调用了call方法并且把this绑定到egg对象上;
用call进行绑定,就相当于在egg对象中增加了一个person函数,其实这里就是this的隐式绑定,
当函数person引用有上下文对象时,就会把函数person调用中的this绑定到这个上下文对象egg了,总的来说就是this指向调用者
var egg = {
name:'蛋老师'
person:function() {
console.log(this.name);
}
};
egg.person();
要实现call方法,就要思考call是从哪里来的
- 每个JavaScript函数其实都是Function对象,而Function对象是构造函数,构造函数是有原型对象的,也就是Function.prototype
- 这个原型对象里有很多属性可以使用,比如call就是在这个原型对象属性里面来的,
- 因此我们要模仿必须在原型对象里面添加新的和call一样的属性,call作为一种属性同时也是一种方法,可以看到在调用call时,后面加了括号
- 既然是方法,那call其实就是一个函数而已,我们可以为原型对象添加一个新的方法
function person(a,b,c,d) {
return {
name: this.name,
a:a,b:b,c:c,d:d
}
}
var egg = {name:'蛋老师'};
Function.prototype.newCall = function (obj) {
if(typeof this !== "function"){
console.error("type error");
}
var obj = obj || window; //如果对象存在就不管了,如果对象不存在就执行window
obj.p = this; //这里开始还没有硬绑定,依旧是隐式绑定,this指向调用者person
var newArguments = [...arguments].slice(1);
var result = obj.p(...newArguments);
delete obj.p; //要把方法删除,因为不能改写来对象
return result
}
var bibi = person.newCall(egg,'点赞','收藏','转发','充电');
console.log(bibi)
2.apply 函数的实现步骤:
apply第二个参数需要传入数组需要判断两种情况:
- 数组为空,直接调用
- 数组不为空,传入形参调用
function person(a,b,c,d){
return{
name: this.name,
a:a,b:b,c:c,d:d
}
}
var egg = {name:'蛋老师'};
Function.prototype.newApply = function(obj){
var obj = obj || window;
obj.p = this;
if(!argumnets[1]){
result = obj.p();
}else{
result = obj.p(...arguments[1])
}
delete obj.p;
return result;
}
var bibi = person.newCall(egg,['点赞','收藏','转发','充电']);
console.log(bibi)
3.bind 函数的实现步骤:
bind与apply和call不同,bind会返回一个函数
bind是具有柯里化特性的
function person() {
return{
name: this.name,
a:a,b:b,c:c
}
}
var egg = {name:'蛋老师'};
Function.prototype.newBind = function(obj){
var that = this,
arr = [...arguments].slice(1);
return function(){
var arr2 = [...arguments],
arrSum = arr.concat(arr2);
return that.apply(
this instanceof that ? this : obj,
arrSum);
}
}
person.newBind(egg,'点赞','投币')('充电');